blob: b5e077af7fa6273839369d4732682dbc6408cb02 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 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 {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100940 struct sockaddr_storage *sk = str2sa(args[1]);
941 if (!sk || sk->ss_family != AF_INET) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100942 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
David du Colombier6f5ccb12011-03-10 22:26:24 +0100946 logsrv.u.in = *(struct sockaddr_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);
Willy Tarreauff011f22011-01-06 17:51:27 +01001061 LIST_INIT(&p->http_req_rules);
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;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001236 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001237
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;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001290
1291 switch (newpeer->addr.ss_family) {
1292 case AF_INET:
1293 ((struct sockaddr_in *)&newpeer->addr)->sin_port = htons(realport);
1294 break;
1295 case AF_INET6:
1296 ((struct sockaddr_in6 *)&newpeer->addr)->sin6_port = htons(realport);
1297 break;
1298 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001299
1300 if (strcmp(newpeer->id, localpeer) == 0) {
1301 /* Current is local peer, it define a frontend */
1302 newpeer->local = 1;
1303
1304 if (!curpeers->peers_fe) {
1305 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1306 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1307 err_code |= ERR_ALERT | ERR_ABORT;
1308 goto out;
1309 }
1310 curpeers->peers_fe->parent = curpeers;
1311
1312 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1313 LIST_INIT(&(curpeers->peers_fe)->acl);
1314 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1315 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1316 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1317 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1318 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1319 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1320
1321 proxy_reset_timeouts(curpeers->peers_fe);
1322
1323 curpeers->peers_fe->last_change = now.tv_sec;
1324 curpeers->peers_fe->id = strdup(args[1]);
1325 curpeers->peers_fe->cap = PR_CAP_FE;
1326 curpeers->peers_fe->maxconn = 65000;
1327 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1328 curpeers->peers_fe->timeout.connect = 5000;
1329 curpeers->peers_fe->accept = peer_accept;
1330 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
1331 if (!str2listener(args[2], curpeers->peers_fe)) {
1332 err_code |= ERR_FATAL;
1333 goto out;
1334 }
1335 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1336 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1337 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1338 curpeers->peers_fe->listen->accept = session_accept;
1339 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1340 curpeers->peers_fe->listen->handler = process_session;
1341 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1342 }
1343 }
1344 } /* neither "peer" nor "peers" */
1345 else if (*args[0] != 0) {
1346 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1347 err_code |= ERR_ALERT | ERR_FATAL;
1348 goto out;
1349 }
1350
1351out:
1352 return err_code;
1353}
1354
1355
Willy Tarreau3842f002009-06-14 11:39:52 +02001356int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357{
1358 static struct proxy *curproxy = NULL;
1359 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001360 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001361 int rc;
1362 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001363 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001364 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365
Willy Tarreau977b8e42006-12-29 14:19:17 +01001366 if (!strcmp(args[0], "listen"))
1367 rc = PR_CAP_LISTEN;
1368 else if (!strcmp(args[0], "frontend"))
1369 rc = PR_CAP_FE | PR_CAP_RS;
1370 else if (!strcmp(args[0], "backend"))
1371 rc = PR_CAP_BE | PR_CAP_RS;
1372 else if (!strcmp(args[0], "ruleset"))
1373 rc = PR_CAP_RS;
1374 else
1375 rc = PR_CAP_NONE;
1376
1377 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 if (!*args[1]) {
1379 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1380 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1381 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_ALERT | ERR_ABORT;
1383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001385
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001386 err = invalid_char(args[1]);
1387 if (err) {
1388 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1389 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001390 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001391 }
1392
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001393 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1394 /*
1395 * If there are two proxies with the same name only following
1396 * combinations are allowed:
1397 *
1398 * listen backend frontend ruleset
1399 * listen - - - -
1400 * backend - - OK -
1401 * frontend - OK - -
1402 * ruleset - - - -
1403 */
1404
1405 if (!strcmp(curproxy->id, args[1]) &&
1406 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1407 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001408 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1409 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1410 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001411 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001412 }
1413 }
1414
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1416 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001417 err_code |= ERR_ALERT | ERR_ABORT;
1418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001420
Willy Tarreau97cb7802010-01-03 20:23:58 +01001421 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 curproxy->next = proxy;
1423 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001424 curproxy->conf.file = file;
1425 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001426 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001428 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429
1430 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001431 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001432 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001433 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001434 err_code |= ERR_FATAL;
1435 goto out;
1436 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001437 new = curproxy->listen;
1438 while (new != last) {
1439 new->conf.file = file;
1440 new->conf.line = linenum;
1441 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001442 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 }
1445
1446 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001447 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001448 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001449
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001452 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001453 curproxy->no_options = defproxy.no_options;
1454 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001455 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001456 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001457 curproxy->except_net = defproxy.except_net;
1458 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001459 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001460 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001462 if (defproxy.fwdfor_hdr_len) {
1463 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1464 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1465 }
1466
Willy Tarreaub86db342009-11-30 11:50:16 +01001467 if (defproxy.orgto_hdr_len) {
1468 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1469 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1470 }
1471
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472 if (curproxy->cap & PR_CAP_FE) {
1473 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001474 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001475 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001476
1477 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001478 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1479 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001480
1481 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483
Willy Tarreau977b8e42006-12-29 14:19:17 +01001484 if (curproxy->cap & PR_CAP_BE) {
1485 curproxy->fullconn = defproxy.fullconn;
1486 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001488 if (defproxy.check_req) {
1489 curproxy->check_req = calloc(1, defproxy.check_len);
1490 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1491 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 if (defproxy.cookie_name)
1495 curproxy->cookie_name = strdup(defproxy.cookie_name);
1496 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001497 if (defproxy.cookie_domain)
1498 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001499
Willy Tarreau31936852010-10-06 16:59:56 +02001500 if (defproxy.cookie_maxidle)
1501 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1502
1503 if (defproxy.cookie_maxlife)
1504 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1505
Emeric Brun647caf12009-06-30 17:57:00 +02001506 if (defproxy.rdp_cookie_name)
1507 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1508 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1509
Willy Tarreau01732802007-11-01 22:48:15 +01001510 if (defproxy.url_param_name)
1511 curproxy->url_param_name = strdup(defproxy.url_param_name);
1512 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001513
Benoitaffb4812009-03-25 13:02:10 +01001514 if (defproxy.hh_name)
1515 curproxy->hh_name = strdup(defproxy.hh_name);
1516 curproxy->hh_len = defproxy.hh_len;
1517 curproxy->hh_match_domain = defproxy.hh_match_domain;
1518
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001519 if (defproxy.iface_name)
1520 curproxy->iface_name = strdup(defproxy.iface_name);
1521 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001524 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001525 if (defproxy.capture_name)
1526 curproxy->capture_name = strdup(defproxy.capture_name);
1527 curproxy->capture_namelen = defproxy.capture_namelen;
1528 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530
Willy Tarreau977b8e42006-12-29 14:19:17 +01001531 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001532 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001533 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001534 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001535 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001536 curproxy->uri_auth = defproxy.uri_auth;
1537 curproxy->mon_net = defproxy.mon_net;
1538 curproxy->mon_mask = defproxy.mon_mask;
1539 if (defproxy.monitor_uri)
1540 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1541 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001542 if (defproxy.defbe.name)
1543 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001544 }
1545
1546 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001547 curproxy->timeout.connect = defproxy.timeout.connect;
1548 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001549 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001550 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001551 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001552 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001553 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001554 curproxy->source_addr = defproxy.source_addr;
1555 }
1556
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 curproxy->mode = defproxy.mode;
1558 curproxy->logfac1 = defproxy.logfac1;
1559 curproxy->logsrv1 = defproxy.logsrv1;
1560 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001561 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 curproxy->logfac2 = defproxy.logfac2;
1563 curproxy->logsrv2 = defproxy.logsrv2;
1564 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001565 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001567 curproxy->conf.used_listener_id = EB_ROOT;
1568 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001569
Willy Tarreau93893792009-07-23 13:19:11 +02001570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 }
1572 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1573 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001574 /* FIXME-20070101: we should do this too at the end of the
1575 * config parsing to free all default values.
1576 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001577 free(defproxy.check_req);
1578 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001579 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001580 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001581 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001582 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001583 free(defproxy.capture_name);
1584 free(defproxy.monitor_uri);
1585 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001586 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001587 free(defproxy.fwdfor_hdr_name);
1588 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001589 free(defproxy.orgto_hdr_name);
1590 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001591
Willy Tarreaua534fea2008-08-03 12:19:50 +02001592 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001593 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001594
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595 /* we cannot free uri_auth because it might already be used */
1596 init_default_instance();
1597 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001598 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 }
1601 else if (curproxy == NULL) {
1602 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001603 err_code |= ERR_ALERT | ERR_FATAL;
1604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
1606
Willy Tarreau977b8e42006-12-29 14:19:17 +01001607
1608 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001610 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001611 int cur_arg;
1612
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 if (curproxy == &defproxy) {
1614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001615 err_code |= ERR_ALERT | ERR_FATAL;
1616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001618 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001619 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620
Emeric Bruned760922010-10-22 17:59:25 +02001621 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001622 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001624 err_code |= ERR_ALERT | ERR_FATAL;
1625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001627
1628 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001629
1630 /* NOTE: the following line might create several listeners if there
1631 * are comma-separated IPs or port ranges. So all further processing
1632 * will have to be applied to all listeners created after last_listen.
1633 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001634 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
1637 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001638
Willy Tarreau90a570f2009-10-04 20:54:54 +02001639 new_listen = curproxy->listen;
1640 while (new_listen != last_listen) {
1641 new_listen->conf.file = file;
1642 new_listen->conf.line = linenum;
1643 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001644 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001645 }
1646
Emeric Bruned760922010-10-22 17:59:25 +02001647 /* Set default global rights and owner for unix bind */
1648 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1649 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1650 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001651 cur_arg = 2;
1652 while (*(args[cur_arg])) {
1653 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1654#ifdef SO_BINDTODEVICE
1655 struct listener *l;
1656
Emeric Bruned760922010-10-22 17:59:25 +02001657 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1658 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1659 file, linenum, args[0], args[cur_arg]);
1660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
1662 }
1663
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001664 if (!*args[cur_arg + 1]) {
1665 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1666 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001669 }
1670
1671 for (l = curproxy->listen; l != last_listen; l = l->next)
1672 l->interface = strdup(args[cur_arg + 1]);
1673
1674 global.last_checks |= LSTCHK_NETADM;
1675
1676 cur_arg += 2;
1677 continue;
1678#else
1679 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1680 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001681 err_code |= ERR_ALERT | ERR_FATAL;
1682 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001683#endif
1684 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001685 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1686#ifdef TCP_MAXSEG
1687 struct listener *l;
1688 int mss;
1689
Emeric Bruned760922010-10-22 17:59:25 +02001690 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1691 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1692 file, linenum, args[0], args[cur_arg]);
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
1695 }
1696
Willy Tarreaube1b9182009-06-14 18:48:19 +02001697 if (!*args[cur_arg + 1]) {
1698 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001702 }
1703
Willy Tarreau48a7e722010-12-24 15:26:39 +01001704 mss = atoi(args[cur_arg + 1]);
1705 if (!mss || abs(mss) > 65535) {
1706 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001707 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001708 err_code |= ERR_ALERT | ERR_FATAL;
1709 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001710 }
1711
1712 for (l = curproxy->listen; l != last_listen; l = l->next)
1713 l->maxseg = mss;
1714
1715 cur_arg += 2;
1716 continue;
1717#else
1718 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1719 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001722#endif
1723 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001724
1725 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1726#ifdef TCP_DEFER_ACCEPT
1727 struct listener *l;
1728
1729 for (l = curproxy->listen; l != last_listen; l = l->next)
1730 l->options |= LI_O_DEF_ACCEPT;
1731
1732 cur_arg ++;
1733 continue;
1734#else
1735 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1736 file, linenum, args[0], args[cur_arg]);
1737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
1739#endif
1740 }
1741
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001742 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001743#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001744 struct listener *l;
1745
Emeric Bruned760922010-10-22 17:59:25 +02001746 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1747 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1748 file, linenum, args[0], args[cur_arg]);
1749 err_code |= ERR_ALERT | ERR_FATAL;
1750 goto out;
1751 }
1752
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001753 for (l = curproxy->listen; l != last_listen; l = l->next)
1754 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001755
1756 cur_arg ++;
1757 continue;
1758#else
1759 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1760 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001763#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001764 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001765
Willy Tarreau8a956912010-10-15 14:27:08 +02001766 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1767 struct listener *l;
1768
1769 for (l = curproxy->listen; l != last_listen; l = l->next)
1770 l->options |= LI_O_ACC_PROXY;
1771
1772 cur_arg ++;
1773 continue;
1774 }
1775
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001776 if (!strcmp(args[cur_arg], "name")) {
1777 struct listener *l;
1778
1779 for (l = curproxy->listen; l != last_listen; l = l->next)
1780 l->name = strdup(args[cur_arg + 1]);
1781
1782 cur_arg += 2;
1783 continue;
1784 }
1785
1786 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001787 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001788 struct listener *l;
1789
1790 if (curproxy->listen->next != last_listen) {
1791 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1792 file, linenum, args[cur_arg]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 if (!*args[cur_arg + 1]) {
1798 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1799 file, linenum, args[cur_arg]);
1800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
1802 }
1803
1804 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001805 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001806
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001807 if (curproxy->listen->luid <= 0) {
1808 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001809 file, linenum);
1810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
1812 }
1813
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001814 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1815 if (node) {
1816 l = container_of(node, struct listener, conf.id);
1817 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1818 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1819 err_code |= ERR_ALERT | ERR_FATAL;
1820 goto out;
1821 }
1822 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1823
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001824 cur_arg += 2;
1825 continue;
1826 }
1827
Emeric Bruned760922010-10-22 17:59:25 +02001828 if (!strcmp(args[cur_arg], "mode")) {
1829
1830 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1831 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1832 file, linenum, args[0], args[cur_arg]);
1833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
1835 }
1836
1837 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1838
1839 cur_arg += 2;
1840 continue;
1841 }
1842
1843 if (!strcmp(args[cur_arg], "uid")) {
1844
1845 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1846 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1847 file, linenum, args[0], args[cur_arg]);
1848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
1850 }
1851
1852 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1853 cur_arg += 2;
1854 continue;
1855 }
1856
1857 if (!strcmp(args[cur_arg], "gid")) {
1858
1859 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1860 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1861 file, linenum, args[0], args[cur_arg]);
1862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
1864 }
1865
1866 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1867 cur_arg += 2;
1868 continue;
1869 }
1870
1871 if (!strcmp(args[cur_arg], "user")) {
1872 struct passwd *user;
1873
1874 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1875 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1876 file, linenum, args[0], args[cur_arg]);
1877 err_code |= ERR_ALERT | ERR_FATAL;
1878 goto out;
1879 }
1880 user = getpwnam(args[cur_arg + 1]);
1881 if (!user) {
1882 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1883 file, linenum, args[0], args[cur_arg + 1 ]);
1884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
1886 }
1887
1888 curproxy->listen->perm.ux.uid = user->pw_uid;
1889 cur_arg += 2;
1890 continue;
1891 }
1892
1893 if (!strcmp(args[cur_arg], "group")) {
1894 struct group *group;
1895
1896 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1897 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1898 file, linenum, args[0], args[cur_arg]);
1899 err_code |= ERR_ALERT | ERR_FATAL;
1900 goto out;
1901 }
1902 group = getgrnam(args[cur_arg + 1]);
1903 if (!group) {
1904 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1905 file, linenum, args[0], args[cur_arg + 1 ]);
1906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
1908 }
1909
1910 curproxy->listen->perm.ux.gid = group->gr_gid;
1911 cur_arg += 2;
1912 continue;
1913 }
1914
Willy Tarreau8a956912010-10-15 14:27:08 +02001915 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 +01001916 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001917 err_code |= ERR_ALERT | ERR_FATAL;
1918 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001919 }
Willy Tarreau93893792009-07-23 13:19:11 +02001920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 }
1922 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1923 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1924 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001926 err_code |= ERR_ALERT | ERR_FATAL;
1927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 }
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 Tarreaubaaee002006-06-26 02:48:02 +02001932 /* flush useless bits */
1933 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001936 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001937 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001938 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001939
Willy Tarreau1c47f852006-07-09 08:22:27 +02001940 if (!*args[1]) {
1941 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001943 err_code |= ERR_ALERT | ERR_FATAL;
1944 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001945 }
1946
Willy Tarreaua534fea2008-08-03 12:19:50 +02001947 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001948 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001949 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001950 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001951 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1952
Willy Tarreau93893792009-07-23 13:19:11 +02001953 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1956 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1957 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1958 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1959 else {
1960 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963 }
1964 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001965 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001966 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001967
1968 if (curproxy == &defproxy) {
1969 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1970 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001971 err_code |= ERR_ALERT | ERR_FATAL;
1972 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001973 }
1974
1975 if (!*args[1]) {
1976 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1977 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001980 }
1981
1982 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001983 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001984
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001985 if (curproxy->uuid <= 0) {
1986 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001987 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001988 err_code |= ERR_ALERT | ERR_FATAL;
1989 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001990 }
1991
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001992 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1993 if (node) {
1994 struct proxy *target = container_of(node, struct proxy, conf.id);
1995 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1996 file, linenum, proxy_type_str(curproxy), curproxy->id,
1997 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1998 err_code |= ERR_ALERT | ERR_FATAL;
1999 goto out;
2000 }
2001 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002002 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002003 else if (!strcmp(args[0], "description")) {
2004 int i, len=0;
2005 char *d;
2006
Cyril Bonté99ed3272010-01-24 23:29:44 +01002007 if (curproxy == &defproxy) {
2008 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2009 file, linenum, args[0]);
2010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
2012 }
2013
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002014 if (!*args[1]) {
2015 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2016 file, linenum, args[0]);
2017 return -1;
2018 }
2019
2020 for(i=1; *args[i]; i++)
2021 len += strlen(args[i])+1;
2022
2023 d = (char *)calloc(1, len);
2024 curproxy->desc = d;
2025
2026 d += sprintf(d, "%s", args[1]);
2027 for(i=2; *args[i]; i++)
2028 d += sprintf(d, " %s", args[i]);
2029
2030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2032 curproxy->state = PR_STSTOPPED;
2033 }
2034 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2035 curproxy->state = PR_STNEW;
2036 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002037 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2038 int cur_arg = 1;
2039 unsigned int set = 0;
2040
2041 while (*args[cur_arg]) {
2042 int u;
2043 if (strcmp(args[cur_arg], "all") == 0) {
2044 set = 0;
2045 break;
2046 }
2047 else if (strcmp(args[cur_arg], "odd") == 0) {
2048 set |= 0x55555555;
2049 }
2050 else if (strcmp(args[cur_arg], "even") == 0) {
2051 set |= 0xAAAAAAAA;
2052 }
2053 else {
2054 u = str2uic(args[cur_arg]);
2055 if (u < 1 || u > 32) {
2056 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002058 err_code |= ERR_ALERT | ERR_FATAL;
2059 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002060 }
2061 if (u > global.nbproc) {
2062 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2063 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002065 }
2066 set |= 1 << (u - 1);
2067 }
2068 cur_arg++;
2069 }
2070 curproxy->bind_proc = set;
2071 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002072 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002073 if (curproxy == &defproxy) {
2074 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002075 err_code |= ERR_ALERT | ERR_FATAL;
2076 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002077 }
2078
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002079 err = invalid_char(args[1]);
2080 if (err) {
2081 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2082 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002083 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002084 }
2085
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002086 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2087 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2088 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002089 err_code |= ERR_ALERT | ERR_FATAL;
2090 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002091 }
2092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2094 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095
Willy Tarreau977b8e42006-12-29 14:19:17 +01002096 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002097 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002098
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 if (*(args[1]) == 0) {
2100 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002105
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002106 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002107 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002108 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002109 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002110 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 curproxy->cookie_name = strdup(args[1]);
2112 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002113
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 cur_arg = 2;
2115 while (*(args[cur_arg])) {
2116 if (!strcmp(args[cur_arg], "rewrite")) {
2117 curproxy->options |= PR_O_COOK_RW;
2118 }
2119 else if (!strcmp(args[cur_arg], "indirect")) {
2120 curproxy->options |= PR_O_COOK_IND;
2121 }
2122 else if (!strcmp(args[cur_arg], "insert")) {
2123 curproxy->options |= PR_O_COOK_INS;
2124 }
2125 else if (!strcmp(args[cur_arg], "nocache")) {
2126 curproxy->options |= PR_O_COOK_NOC;
2127 }
2128 else if (!strcmp(args[cur_arg], "postonly")) {
2129 curproxy->options |= PR_O_COOK_POST;
2130 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002131 else if (!strcmp(args[cur_arg], "preserve")) {
2132 curproxy->options2 |= PR_O2_COOK_PSV;
2133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002134 else if (!strcmp(args[cur_arg], "prefix")) {
2135 curproxy->options |= PR_O_COOK_PFX;
2136 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002137 else if (!strcmp(args[cur_arg], "domain")) {
2138 if (!*args[cur_arg + 1]) {
2139 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2140 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002143 }
2144
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002145 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002146 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002147 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2148 " dots nor does not start with a dot."
2149 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002150 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002151 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002152 }
2153
2154 err = invalid_domainchar(args[cur_arg + 1]);
2155 if (err) {
2156 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2157 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002160 }
2161
Willy Tarreau68a897b2009-12-03 23:28:34 +01002162 if (!curproxy->cookie_domain) {
2163 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2164 } else {
2165 /* one domain was already specified, add another one by
2166 * building the string which will be returned along with
2167 * the cookie.
2168 */
2169 char *new_ptr;
2170 int new_len = strlen(curproxy->cookie_domain) +
2171 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2172 new_ptr = malloc(new_len);
2173 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2174 free(curproxy->cookie_domain);
2175 curproxy->cookie_domain = new_ptr;
2176 }
Willy Tarreau31936852010-10-06 16:59:56 +02002177 cur_arg++;
2178 }
2179 else if (!strcmp(args[cur_arg], "maxidle")) {
2180 unsigned int maxidle;
2181 const char *res;
2182
2183 if (!*args[cur_arg + 1]) {
2184 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2185 file, linenum, args[cur_arg]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189
2190 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2191 if (res) {
2192 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2193 file, linenum, *res, args[cur_arg]);
2194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
2196 }
2197 curproxy->cookie_maxidle = maxidle;
2198 cur_arg++;
2199 }
2200 else if (!strcmp(args[cur_arg], "maxlife")) {
2201 unsigned int maxlife;
2202 const char *res;
2203
2204 if (!*args[cur_arg + 1]) {
2205 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2206 file, linenum, args[cur_arg]);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210
2211 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2212 if (res) {
2213 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2214 file, linenum, *res, args[cur_arg]);
2215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
2217 }
2218 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002219 cur_arg++;
2220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002221 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002222 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 +02002223 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 }
2227 cur_arg++;
2228 }
2229 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2230 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2231 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 }
2234
2235 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2236 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2237 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002238 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002240
2241 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2242 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2243 file, linenum);
2244 err_code |= ERR_ALERT | ERR_FATAL;
2245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002246 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002247 else if (!strcmp(args[0], "persist")) { /* persist */
2248 if (*(args[1]) == 0) {
2249 Alert("parsing [%s:%d] : missing persist method.\n",
2250 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002253 }
2254
2255 if (!strncmp(args[1], "rdp-cookie", 10)) {
2256 curproxy->options2 |= PR_O2_RDPC_PRST;
2257
Emeric Brunb982a3d2010-01-04 15:45:53 +01002258 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002259 const char *beg, *end;
2260
2261 beg = args[1] + 11;
2262 end = strchr(beg, ')');
2263
2264 if (!end || end == beg) {
2265 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2266 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002269 }
2270
2271 free(curproxy->rdp_cookie_name);
2272 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2273 curproxy->rdp_cookie_len = end-beg;
2274 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002275 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002276 free(curproxy->rdp_cookie_name);
2277 curproxy->rdp_cookie_name = strdup("msts");
2278 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2279 }
2280 else { /* syntax */
2281 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2282 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002283 err_code |= ERR_ALERT | ERR_FATAL;
2284 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002285 }
2286 }
2287 else {
2288 Alert("parsing [%s:%d] : unknown persist method.\n",
2289 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002292 }
2293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002295 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002297 if (curproxy == &defproxy) {
2298 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
2301 }
2302
Willy Tarreau977b8e42006-12-29 14:19:17 +01002303 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002304 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002305
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002307 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002308 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 }
2312 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002313 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 curproxy->appsession_name = strdup(args[1]);
2315 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2316 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002317 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2318 if (err) {
2319 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2320 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002323 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002324 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002325
Willy Tarreau51041c72007-09-09 21:56:53 +02002326 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_ALERT | ERR_ABORT;
2329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002331
2332 cur_arg = 6;
2333 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002334 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2335 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002336 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002337 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002338 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002339 } else if (!strcmp(args[cur_arg], "prefix")) {
2340 curproxy->options2 |= PR_O2_AS_PFX;
2341 } else if (!strcmp(args[cur_arg], "mode")) {
2342 if (!*args[cur_arg + 1]) {
2343 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2344 file, linenum, args[0], args[cur_arg]);
2345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
2347 }
2348
2349 cur_arg++;
2350 if (!strcmp(args[cur_arg], "query-string")) {
2351 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2352 curproxy->options2 |= PR_O2_AS_M_QS;
2353 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2354 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2355 curproxy->options2 |= PR_O2_AS_M_PP;
2356 } else {
2357 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
2360 }
2361 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002362 cur_arg++;
2363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 } /* Url App Session */
2365 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002366 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002368
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002370 if (curproxy == &defproxy) {
2371 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
2374 }
2375
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 if (*(args[4]) == 0) {
2377 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2378 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002379 err_code |= ERR_ALERT | ERR_FATAL;
2380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002382 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 curproxy->capture_name = strdup(args[2]);
2384 curproxy->capture_namelen = strlen(curproxy->capture_name);
2385 curproxy->capture_len = atol(args[4]);
2386 if (curproxy->capture_len >= CAPTURE_LEN) {
2387 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2388 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002389 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 curproxy->capture_len = CAPTURE_LEN - 1;
2391 }
2392 curproxy->to_log |= LW_COOKIE;
2393 }
2394 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2395 struct cap_hdr *hdr;
2396
2397 if (curproxy == &defproxy) {
2398 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 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 }
2402
2403 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2404 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2405 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 }
2409
2410 hdr = calloc(sizeof(struct cap_hdr), 1);
2411 hdr->next = curproxy->req_cap;
2412 hdr->name = strdup(args[3]);
2413 hdr->namelen = strlen(args[3]);
2414 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002415 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 hdr->index = curproxy->nb_req_cap++;
2417 curproxy->req_cap = hdr;
2418 curproxy->to_log |= LW_REQHDR;
2419 }
2420 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2421 struct cap_hdr *hdr;
2422
2423 if (curproxy == &defproxy) {
2424 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 +02002425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 }
2428
2429 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2430 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2431 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
2435 hdr = calloc(sizeof(struct cap_hdr), 1);
2436 hdr->next = curproxy->rsp_cap;
2437 hdr->name = strdup(args[3]);
2438 hdr->namelen = strlen(args[3]);
2439 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002440 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 hdr->index = curproxy->nb_rsp_cap++;
2442 curproxy->rsp_cap = hdr;
2443 curproxy->to_log |= LW_RSPHDR;
2444 }
2445 else {
2446 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2447 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 }
2451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002453 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002455
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 if (*(args[1]) == 0) {
2457 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 }
2462 curproxy->conn_retries = atol(args[1]);
2463 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002464 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002465 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002466
2467 if (curproxy == &defproxy) {
2468 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
2472
Willy Tarreauff011f22011-01-06 17:51:27 +01002473 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002474 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2475 file, linenum, args[0]);
2476 err_code |= ERR_WARN;
2477 }
2478
Willy Tarreauff011f22011-01-06 17:51:27 +01002479 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002480
Willy Tarreauff011f22011-01-06 17:51:27 +01002481 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002482 err_code |= ERR_ALERT | ERR_ABORT;
2483 goto out;
2484 }
2485
Willy Tarreauff011f22011-01-06 17:51:27 +01002486 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2487 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002488 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002489 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002490 if (curproxy == &defproxy) {
2491 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002494 }
2495
Willy Tarreauef6494c2010-01-28 17:12:36 +01002496 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002497 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2498 file, linenum, args[0]);
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 }
2502
Willy Tarreauef6494c2010-01-28 17:12:36 +01002503 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002504 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2505 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002508 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002509
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002510 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002511 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002512 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002513 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002514 struct redirect_rule *rule;
2515 int cur_arg;
2516 int type = REDIRECT_TYPE_NONE;
2517 int code = 302;
2518 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002519 char *cookie = NULL;
2520 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002521 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002522
Cyril Bonté99ed3272010-01-24 23:29:44 +01002523 if (curproxy == &defproxy) {
2524 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
2527 }
2528
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002529 cur_arg = 1;
2530 while (*(args[cur_arg])) {
2531 if (!strcmp(args[cur_arg], "location")) {
2532 if (!*args[cur_arg + 1]) {
2533 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2534 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002537 }
2538
2539 type = REDIRECT_TYPE_LOCATION;
2540 cur_arg++;
2541 destination = args[cur_arg];
2542 }
2543 else if (!strcmp(args[cur_arg], "prefix")) {
2544 if (!*args[cur_arg + 1]) {
2545 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2546 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002549 }
2550
2551 type = REDIRECT_TYPE_PREFIX;
2552 cur_arg++;
2553 destination = args[cur_arg];
2554 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002555 else if (!strcmp(args[cur_arg], "set-cookie")) {
2556 if (!*args[cur_arg + 1]) {
2557 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2558 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002561 }
2562
2563 cur_arg++;
2564 cookie = args[cur_arg];
2565 cookie_set = 1;
2566 }
2567 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2568 if (!*args[cur_arg + 1]) {
2569 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2570 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_FATAL;
2572 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002573 }
2574
2575 cur_arg++;
2576 cookie = args[cur_arg];
2577 cookie_set = 0;
2578 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002579 else if (!strcmp(args[cur_arg],"code")) {
2580 if (!*args[cur_arg + 1]) {
2581 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002585 }
2586 cur_arg++;
2587 code = atol(args[cur_arg]);
2588 if (code < 301 || code > 303) {
2589 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2590 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002593 }
2594 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002595 else if (!strcmp(args[cur_arg],"drop-query")) {
2596 flags |= REDIRECT_FLAG_DROP_QS;
2597 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002598 else if (!strcmp(args[cur_arg],"append-slash")) {
2599 flags |= REDIRECT_FLAG_APPEND_SLASH;
2600 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002601 else if (strcmp(args[cur_arg], "if") == 0 ||
2602 strcmp(args[cur_arg], "unless") == 0) {
2603 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2604 if (!cond) {
2605 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2606 file, linenum, args[0]);
2607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
2609 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002610 break;
2611 }
2612 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002613 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 +02002614 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002617 }
2618 cur_arg++;
2619 }
2620
2621 if (type == REDIRECT_TYPE_NONE) {
2622 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002626 }
2627
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002628 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2629 rule->cond = cond;
2630 rule->rdr_str = strdup(destination);
2631 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002632 if (cookie) {
2633 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002634 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002635 */
2636 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002637 if (cookie_set) {
2638 rule->cookie_str = malloc(rule->cookie_len + 10);
2639 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2640 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2641 rule->cookie_len += 9;
2642 } else {
2643 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002644 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002645 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2646 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002647 }
2648 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002649 rule->type = type;
2650 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002651 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002652 LIST_INIT(&rule->list);
2653 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002654 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2655 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002656 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002657 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002658 struct switching_rule *rule;
2659
Willy Tarreaub099aca2008-10-12 17:26:37 +02002660 if (curproxy == &defproxy) {
2661 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002664 }
2665
Willy Tarreau55ea7572007-06-17 19:56:27 +02002666 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002668
2669 if (*(args[1]) == 0) {
2670 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002673 }
2674
Willy Tarreauef6494c2010-01-28 17:12:36 +01002675 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002676 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2677 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002680 }
2681
Willy Tarreauef6494c2010-01-28 17:12:36 +01002682 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002683 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002684 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002687 }
2688
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002689 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002690
Willy Tarreau55ea7572007-06-17 19:56:27 +02002691 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2692 rule->cond = cond;
2693 rule->be.name = strdup(args[1]);
2694 LIST_INIT(&rule->list);
2695 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2696 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002697 else if ((!strcmp(args[0], "force-persist")) ||
2698 (!strcmp(args[0], "ignore-persist"))) {
2699 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002700
2701 if (curproxy == &defproxy) {
2702 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
2705 }
2706
2707 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2708 err_code |= ERR_WARN;
2709
Willy Tarreauef6494c2010-01-28 17:12:36 +01002710 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002711 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2712 file, linenum, args[0]);
2713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
2715 }
2716
Willy Tarreauef6494c2010-01-28 17:12:36 +01002717 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002718 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2719 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
2722 }
2723
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002724 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002725
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002726 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002727 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002728 if (!strcmp(args[0], "force-persist")) {
2729 rule->type = PERSIST_TYPE_FORCE;
2730 } else {
2731 rule->type = PERSIST_TYPE_IGNORE;
2732 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002733 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002734 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002735 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002736 else if (!strcmp(args[0], "stick-table")) {
2737 int myidx = 1;
2738
Emeric Brun32da3c42010-09-23 18:39:19 +02002739 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002740 curproxy->table.type = (unsigned int)-1;
2741 while (*args[myidx]) {
2742 const char *err;
2743
2744 if (strcmp(args[myidx], "size") == 0) {
2745 myidx++;
2746 if (!*(args[myidx])) {
2747 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2748 file, linenum, args[myidx-1]);
2749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
2751 }
2752 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2753 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2754 file, linenum, *err, args[myidx-1]);
2755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
2757 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002758 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002759 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002760 else if (strcmp(args[myidx], "peers") == 0) {
2761 myidx++;
2762 if (!*(args[myidx])) {
2763 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2764 file, linenum, args[myidx-1]);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
2767 }
2768 curproxy->table.peers.name = strdup(args[myidx++]);
2769 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002770 else if (strcmp(args[myidx], "expire") == 0) {
2771 myidx++;
2772 if (!*(args[myidx])) {
2773 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2774 file, linenum, args[myidx-1]);
2775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
2777 }
2778 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2779 if (err) {
2780 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2781 file, linenum, *err, args[myidx-1]);
2782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
2784 }
2785 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002786 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002787 }
2788 else if (strcmp(args[myidx], "nopurge") == 0) {
2789 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002790 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002791 }
2792 else if (strcmp(args[myidx], "type") == 0) {
2793 myidx++;
2794 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2795 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2796 file, linenum, args[myidx]);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
2799 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002800 /* myidx already points to next arg */
2801 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002802 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002803 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002804 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002805
2806 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002807 nw = args[myidx];
2808 while (*nw) {
2809 /* the "store" keyword supports a comma-separated list */
2810 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002811 sa = NULL; /* store arg */
2812 while (*nw && *nw != ',') {
2813 if (*nw == '(') {
2814 *nw = 0;
2815 sa = ++nw;
2816 while (*nw != ')') {
2817 if (!*nw) {
2818 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2819 file, linenum, args[0], cw);
2820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
2822 }
2823 nw++;
2824 }
2825 *nw = '\0';
2826 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002827 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002828 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002829 if (*nw)
2830 *nw++ = '\0';
2831 type = stktable_get_data_type(cw);
2832 if (type < 0) {
2833 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2834 file, linenum, args[0], cw);
2835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
2837 }
Willy Tarreauac782882010-06-20 10:41:54 +02002838
2839 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2840 switch (err) {
2841 case PE_NONE: break;
2842 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002843 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2844 file, linenum, args[0], cw);
2845 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002846 break;
2847
2848 case PE_ARG_MISSING:
2849 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2850 file, linenum, args[0], cw);
2851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
2853
2854 case PE_ARG_NOT_USED:
2855 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2856 file, linenum, args[0], cw);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859
2860 default:
2861 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2862 file, linenum, args[0], cw);
2863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002865 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002866 }
2867 myidx++;
2868 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002869 else {
2870 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2871 file, linenum, args[myidx]);
2872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002874 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002875 }
2876
2877 if (!curproxy->table.size) {
2878 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2879 file, linenum);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
2882 }
2883
2884 if (curproxy->table.type == (unsigned int)-1) {
2885 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2886 file, linenum);
2887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
2889 }
2890 }
2891 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002892 struct sticking_rule *rule;
2893 struct pattern_expr *expr;
2894 int myidx = 0;
2895 const char *name = NULL;
2896 int flags;
2897
2898 if (curproxy == &defproxy) {
2899 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
2902 }
2903
2904 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2905 err_code |= ERR_WARN;
2906 goto out;
2907 }
2908
2909 myidx++;
2910 if ((strcmp(args[myidx], "store") == 0) ||
2911 (strcmp(args[myidx], "store-request") == 0)) {
2912 myidx++;
2913 flags = STK_IS_STORE;
2914 }
2915 else if (strcmp(args[myidx], "store-response") == 0) {
2916 myidx++;
2917 flags = STK_IS_STORE | STK_ON_RSP;
2918 }
2919 else if (strcmp(args[myidx], "match") == 0) {
2920 myidx++;
2921 flags = STK_IS_MATCH;
2922 }
2923 else if (strcmp(args[myidx], "on") == 0) {
2924 myidx++;
2925 flags = STK_IS_MATCH | STK_IS_STORE;
2926 }
2927 else {
2928 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
2931 }
2932
2933 if (*(args[myidx]) == 0) {
2934 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937 }
2938
Emeric Brun485479d2010-09-23 18:02:19 +02002939 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002940 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002941 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945
2946 if (flags & STK_ON_RSP) {
2947 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2948 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2949 file, linenum, args[0], expr->fetch->kw);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953 } else {
2954 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2955 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2956 file, linenum, args[0], expr->fetch->kw);
2957 err_code |= ERR_ALERT | ERR_FATAL;
2958 goto out;
2959 }
2960 }
2961
2962 if (strcmp(args[myidx], "table") == 0) {
2963 myidx++;
2964 name = args[myidx++];
2965 }
2966
Willy Tarreauef6494c2010-01-28 17:12:36 +01002967 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2968 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002969 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2970 file, linenum, args[0]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002974 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002975 else if (*(args[myidx])) {
2976 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2977 file, linenum, args[0], args[myidx]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
Emeric Brun97679e72010-09-23 17:56:44 +02002981 if (flags & STK_ON_RSP)
2982 err_code |= warnif_cond_requires_req(cond, file, linenum);
2983 else
2984 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002985
Emeric Brunb982a3d2010-01-04 15:45:53 +01002986 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2987 rule->cond = cond;
2988 rule->expr = expr;
2989 rule->flags = flags;
2990 rule->table.name = name ? strdup(name) : NULL;
2991 LIST_INIT(&rule->list);
2992 if (flags & STK_ON_RSP)
2993 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2994 else
2995 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002998 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002999 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003000
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3002 curproxy->uri_auth = NULL; /* we must detach from the default config */
3003
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003004 if (!*args[1]) {
3005 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003006 } else if (!strcmp(args[1], "admin")) {
3007 struct stats_admin_rule *rule;
3008
3009 if (curproxy == &defproxy) {
3010 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
3013 }
3014
3015 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3016 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3017 err_code |= ERR_ALERT | ERR_ABORT;
3018 goto out;
3019 }
3020
3021 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3022 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3023 file, linenum, args[0], args[1]);
3024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026 }
3027 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3028 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3029 file, linenum, args[0], args[1]);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
3033
3034 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3035
3036 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3037 rule->cond = cond;
3038 LIST_INIT(&rule->list);
3039 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 } else if (!strcmp(args[1], "uri")) {
3041 if (*(args[2]) == 0) {
3042 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3046 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_ABORT;
3048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 }
3050 } else if (!strcmp(args[1], "realm")) {
3051 if (*(args[2]) == 0) {
3052 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3056 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003057 err_code |= ERR_ALERT | ERR_ABORT;
3058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003060 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003061 unsigned interval;
3062
3063 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3064 if (err) {
3065 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3066 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003069 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3070 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_ABORT;
3072 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003073 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003074 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003075 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003076
3077 if (curproxy == &defproxy) {
3078 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
3082
3083 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3084 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3085 err_code |= ERR_ALERT | ERR_ABORT;
3086 goto out;
3087 }
3088
Willy Tarreauff011f22011-01-06 17:51:27 +01003089 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3090 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003091 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3092 file, linenum, args[0]);
3093 err_code |= ERR_WARN;
3094 }
3095
Willy Tarreauff011f22011-01-06 17:51:27 +01003096 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003097
Willy Tarreauff011f22011-01-06 17:51:27 +01003098 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003099 err_code |= ERR_ALERT | ERR_ABORT;
3100 goto out;
3101 }
3102
Willy Tarreauff011f22011-01-06 17:51:27 +01003103 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3104 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003105
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 } else if (!strcmp(args[1], "auth")) {
3107 if (*(args[2]) == 0) {
3108 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3112 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_ALERT | ERR_ABORT;
3114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 }
3116 } else if (!strcmp(args[1], "scope")) {
3117 if (*(args[2]) == 0) {
3118 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3122 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_ALERT | ERR_ABORT;
3124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 }
3126 } else if (!strcmp(args[1], "enable")) {
3127 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3128 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_ABORT;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003132 } else if (!strcmp(args[1], "hide-version")) {
3133 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3134 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003135 err_code |= ERR_ALERT | ERR_ABORT;
3136 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003137 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003138 } else if (!strcmp(args[1], "show-legends")) {
3139 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3140 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3141 err_code |= ERR_ALERT | ERR_ABORT;
3142 goto out;
3143 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003144 } else if (!strcmp(args[1], "show-node")) {
3145
3146 if (*args[2]) {
3147 int i;
3148 char c;
3149
3150 for (i=0; args[2][i]; i++) {
3151 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003152 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3153 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003154 break;
3155 }
3156
3157 if (!i || args[2][i]) {
3158 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3159 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3160 file, linenum, args[0], args[1]);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
3164 }
3165
3166 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3167 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3168 err_code |= ERR_ALERT | ERR_ABORT;
3169 goto out;
3170 }
3171 } else if (!strcmp(args[1], "show-desc")) {
3172 char *desc = NULL;
3173
3174 if (*args[2]) {
3175 int i, len=0;
3176 char *d;
3177
3178 for(i=2; *args[i]; i++)
3179 len += strlen(args[i])+1;
3180
3181 desc = d = (char *)calloc(1, len);
3182
3183 d += sprintf(d, "%s", args[2]);
3184 for(i=3; *args[i]; i++)
3185 d += sprintf(d, " %s", args[i]);
3186 }
3187
3188 if (!*args[2] && !global.desc)
3189 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3190 file, linenum, args[1]);
3191 else {
3192 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3193 free(desc);
3194 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3195 err_code |= ERR_ALERT | ERR_ABORT;
3196 goto out;
3197 }
3198 free(desc);
3199 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003201stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003202 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 +01003203 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 }
3207 }
3208 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003209 int optnum;
3210
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003211 if (*(args[1]) == '\0') {
3212 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003217
3218 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3219 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003220 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3221 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3222 file, linenum, cfg_opts[optnum].name);
3223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
3225 }
Willy Tarreau93893792009-07-23 13:19:11 +02003226 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3227 err_code |= ERR_WARN;
3228 goto out;
3229 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003230
Willy Tarreau3842f002009-06-14 11:39:52 +02003231 curproxy->no_options &= ~cfg_opts[optnum].val;
3232 curproxy->options &= ~cfg_opts[optnum].val;
3233
3234 switch (kwm) {
3235 case KWM_STD:
3236 curproxy->options |= cfg_opts[optnum].val;
3237 break;
3238 case KWM_NO:
3239 curproxy->no_options |= cfg_opts[optnum].val;
3240 break;
3241 case KWM_DEF: /* already cleared */
3242 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003243 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003244
Willy Tarreau93893792009-07-23 13:19:11 +02003245 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003246 }
3247 }
3248
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003249 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3250 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003251 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3252 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3253 file, linenum, cfg_opts2[optnum].name);
3254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
3256 }
Willy Tarreau93893792009-07-23 13:19:11 +02003257 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3258 err_code |= ERR_WARN;
3259 goto out;
3260 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003261
Willy Tarreau3842f002009-06-14 11:39:52 +02003262 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3263 curproxy->options2 &= ~cfg_opts2[optnum].val;
3264
3265 switch (kwm) {
3266 case KWM_STD:
3267 curproxy->options2 |= cfg_opts2[optnum].val;
3268 break;
3269 case KWM_NO:
3270 curproxy->no_options2 |= cfg_opts2[optnum].val;
3271 break;
3272 case KWM_DEF: /* already cleared */
3273 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003274 }
Willy Tarreau93893792009-07-23 13:19:11 +02003275 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003276 }
3277 }
3278
Willy Tarreau3842f002009-06-14 11:39:52 +02003279 if (kwm != KWM_STD) {
3280 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003281 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003284 }
3285
Emeric Brun3a058f32009-06-30 18:26:00 +02003286 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003288 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003290 if (*(args[2]) != '\0') {
3291 if (!strcmp(args[2], "clf")) {
3292 curproxy->options2 |= PR_O2_CLFLOG;
3293 } else {
3294 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003297 }
3298 }
3299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 else if (!strcmp(args[1], "tcplog"))
3301 /* generate a detailed TCP log */
3302 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 else if (!strcmp(args[1], "tcpka")) {
3304 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003305 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307
3308 if (curproxy->cap & PR_CAP_FE)
3309 curproxy->options |= PR_O_TCP_CLI_KA;
3310 if (curproxy->cap & PR_CAP_BE)
3311 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 }
3313 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003314 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003315 err_code |= ERR_WARN;
3316
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003318 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003319 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003320 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003321 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003322 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003323 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003324 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003325 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 if (!*args[2]) { /* no argument */
3327 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3328 curproxy->check_len = strlen(DEF_CHECK_REQ);
3329 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003330 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 curproxy->check_req = (char *)malloc(reqlen);
3332 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003333 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003335 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336 if (*args[4])
3337 reqlen += strlen(args[4]);
3338 else
3339 reqlen += strlen("HTTP/1.0");
3340
3341 curproxy->check_req = (char *)malloc(reqlen);
3342 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003343 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003345 }
3346 else if (!strcmp(args[1], "ssl-hello-chk")) {
3347 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003348 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003350
Willy Tarreaua534fea2008-08-03 12:19:50 +02003351 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003352 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003353 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003354 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003355 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003356 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003357 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003358 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 }
Willy Tarreau23677902007-05-08 23:50:35 +02003360 else if (!strcmp(args[1], "smtpchk")) {
3361 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003362 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003363 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003364 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003365 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003366 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003367 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003368 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003369 curproxy->options |= PR_O_SMTP_CHK;
3370
3371 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3372 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3373 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3374 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3375 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3376 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3377 curproxy->check_req = (char *)malloc(reqlen);
3378 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3379 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3380 } else {
3381 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3382 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3383 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3384 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3385 }
3386 }
3387 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003388 else if (!strcmp(args[1], "pgsql-check")) {
3389 /* use PostgreSQL request to check servers' health */
3390 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3391 err_code |= ERR_WARN;
3392
3393 free(curproxy->check_req);
3394 curproxy->check_req = NULL;
3395 curproxy->options &= ~PR_O_HTTP_CHK;
3396 curproxy->options &= ~PR_O_SMTP_CHK;
3397 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3398 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3399 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3400 curproxy->options2 |= PR_O2_PGSQL_CHK;
3401
3402 if (*(args[2])) {
3403 int cur_arg = 2;
3404
3405 while (*(args[cur_arg])) {
3406 if (strcmp(args[cur_arg], "user") == 0) {
3407 char * packet;
3408 uint32_t packet_len;
3409 uint32_t pv;
3410
3411 /* suboption header - needs additional argument for it */
3412 if (*(args[cur_arg+1]) == 0) {
3413 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3414 file, linenum, args[0], args[1], args[cur_arg]);
3415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
3417 }
3418
3419 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3420 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3421 pv = htonl(0x30000); /* protocol version 3.0 */
3422
3423 packet = (char*) calloc(1, packet_len);
3424
3425 memcpy(packet + 4, &pv, 4);
3426
3427 /* copy "user" */
3428 memcpy(packet + 8, "user", 4);
3429
3430 /* copy username */
3431 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3432
3433 free(curproxy->check_req);
3434 curproxy->check_req = packet;
3435 curproxy->check_len = packet_len;
3436
3437 packet_len = htonl(packet_len);
3438 memcpy(packet, &packet_len, 4);
3439 cur_arg += 2;
3440 } else {
3441 /* unknown suboption - catchall */
3442 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3443 file, linenum, args[0], args[1]);
3444 err_code |= ERR_ALERT | ERR_FATAL;
3445 goto out;
3446 }
3447 } /* end while loop */
3448 }
3449 }
3450
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003451 else if (!strcmp(args[1], "mysql-check")) {
3452 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003453 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3454 err_code |= ERR_WARN;
3455
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003456 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003457 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003458 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003459 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003460 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003461 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003462 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003463 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003464
3465 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3466 * const char mysql40_client_auth_pkt[] = {
3467 * "\x0e\x00\x00" // packet length
3468 * "\x01" // packet number
3469 * "\x00\x00" // client capabilities
3470 * "\x00\x00\x01" // max packet
3471 * "haproxy\x00" // username (null terminated string)
3472 * "\x00" // filler (always 0x00)
3473 * "\x01\x00\x00" // packet length
3474 * "\x00" // packet number
3475 * "\x01" // COM_QUIT command
3476 * };
3477 */
3478
3479 if (*(args[2])) {
3480 int cur_arg = 2;
3481
3482 while (*(args[cur_arg])) {
3483 if (strcmp(args[cur_arg], "user") == 0) {
3484 char *mysqluser;
3485 int packetlen, reqlen, userlen;
3486
3487 /* suboption header - needs additional argument for it */
3488 if (*(args[cur_arg+1]) == 0) {
3489 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3490 file, linenum, args[0], args[1], args[cur_arg]);
3491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
3493 }
3494 mysqluser = args[cur_arg + 1];
3495 userlen = strlen(mysqluser);
3496 packetlen = userlen + 7;
3497 reqlen = packetlen + 9;
3498
3499 free(curproxy->check_req);
3500 curproxy->check_req = (char *)calloc(1, reqlen);
3501 curproxy->check_len = reqlen;
3502
3503 snprintf(curproxy->check_req, 4, "%c%c%c",
3504 ((unsigned char) packetlen & 0xff),
3505 ((unsigned char) (packetlen >> 8) & 0xff),
3506 ((unsigned char) (packetlen >> 16) & 0xff));
3507
3508 curproxy->check_req[3] = 1;
3509 curproxy->check_req[8] = 1;
3510 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3511 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3512 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3513 cur_arg += 2;
3514 } else {
3515 /* unknown suboption - catchall */
3516 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3517 file, linenum, args[0], args[1]);
3518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
3520 }
3521 } /* end while loop */
3522 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003523 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003524 else if (!strcmp(args[1], "ldap-check")) {
3525 /* use LDAP request to check servers' health */
3526 free(curproxy->check_req);
3527 curproxy->check_req = NULL;
3528 curproxy->options &= ~PR_O_HTTP_CHK;
3529 curproxy->options &= ~PR_O_SMTP_CHK;
3530 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3531 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003532 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003533 curproxy->options2 |= PR_O2_LDAP_CHK;
3534
3535 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3536 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3537 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3538 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003539 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003540 int cur_arg;
3541
3542 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3543 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003544 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003545
3546 curproxy->options |= PR_O_FWDFOR;
3547
3548 free(curproxy->fwdfor_hdr_name);
3549 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3550 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3551
3552 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3553 cur_arg = 2;
3554 while (*(args[cur_arg])) {
3555 if (!strcmp(args[cur_arg], "except")) {
3556 /* suboption except - needs additional argument for it */
3557 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3558 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3559 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003562 }
3563 /* flush useless bits */
3564 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003565 cur_arg += 2;
3566 } else if (!strcmp(args[cur_arg], "header")) {
3567 /* suboption header - needs additional argument for it */
3568 if (*(args[cur_arg+1]) == 0) {
3569 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3570 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003573 }
3574 free(curproxy->fwdfor_hdr_name);
3575 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3576 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3577 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003578 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003579 /* unknown suboption - catchall */
3580 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3581 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003584 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003585 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003586 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003587 else if (!strcmp(args[1], "originalto")) {
3588 int cur_arg;
3589
3590 /* insert x-original-to field, but not for the IP address listed as an except.
3591 * set default options (ie: bitfield, header name, etc)
3592 */
3593
3594 curproxy->options |= PR_O_ORGTO;
3595
3596 free(curproxy->orgto_hdr_name);
3597 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3598 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3599
3600 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3601 cur_arg = 2;
3602 while (*(args[cur_arg])) {
3603 if (!strcmp(args[cur_arg], "except")) {
3604 /* suboption except - needs additional argument for it */
3605 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3606 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3607 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003610 }
3611 /* flush useless bits */
3612 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3613 cur_arg += 2;
3614 } else if (!strcmp(args[cur_arg], "header")) {
3615 /* suboption header - needs additional argument for it */
3616 if (*(args[cur_arg+1]) == 0) {
3617 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3618 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003621 }
3622 free(curproxy->orgto_hdr_name);
3623 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3624 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3625 cur_arg += 2;
3626 } else {
3627 /* unknown suboption - catchall */
3628 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3629 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003632 }
3633 } /* end while loop */
3634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 else {
3636 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 }
Willy Tarreau93893792009-07-23 13:19:11 +02003640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003642 else if (!strcmp(args[0], "default_backend")) {
3643 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003644 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003645
3646 if (*(args[1]) == 0) {
3647 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003650 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003651 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003652 curproxy->defbe.name = strdup(args[1]);
3653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003655 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003657
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003658 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 /* enable reconnections to dispatch */
3662 curproxy->options |= PR_O_REDISP;
3663 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003664 else if (!strcmp(args[0], "http-check")) {
3665 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003667
3668 if (strcmp(args[1], "disable-on-404") == 0) {
3669 /* enable a graceful server shutdown on an HTTP 404 response */
3670 curproxy->options |= PR_O_DISABLE404;
3671 }
Willy Tarreauef781042010-01-27 11:53:01 +01003672 else if (strcmp(args[1], "send-state") == 0) {
3673 /* enable emission of the apparent state of a server in HTTP checks */
3674 curproxy->options2 |= PR_O2_CHK_SNDST;
3675 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003676 else if (strcmp(args[1], "expect") == 0) {
3677 const char *ptr_arg;
3678 int cur_arg;
3679
3680 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3681 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
3684 }
3685
3686 cur_arg = 2;
3687 /* consider exclamation marks, sole or at the beginning of a word */
3688 while (*(ptr_arg = args[cur_arg])) {
3689 while (*ptr_arg == '!') {
3690 curproxy->options2 ^= PR_O2_EXP_INV;
3691 ptr_arg++;
3692 }
3693 if (*ptr_arg)
3694 break;
3695 cur_arg++;
3696 }
3697 /* now ptr_arg points to the beginning of a word past any possible
3698 * exclamation mark, and cur_arg is the argument which holds this word.
3699 */
3700 if (strcmp(ptr_arg, "status") == 0) {
3701 if (!*(args[cur_arg + 1])) {
3702 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3703 file, linenum, args[0], args[1], ptr_arg);
3704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
3706 }
3707 curproxy->options2 |= PR_O2_EXP_STS;
3708 curproxy->expect_str = strdup(args[cur_arg + 1]);
3709 }
3710 else if (strcmp(ptr_arg, "string") == 0) {
3711 if (!*(args[cur_arg + 1])) {
3712 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3713 file, linenum, args[0], args[1], ptr_arg);
3714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
3716 }
3717 curproxy->options2 |= PR_O2_EXP_STR;
3718 curproxy->expect_str = strdup(args[cur_arg + 1]);
3719 }
3720 else if (strcmp(ptr_arg, "rstatus") == 0) {
3721 if (!*(args[cur_arg + 1])) {
3722 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3723 file, linenum, args[0], args[1], ptr_arg);
3724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
3726 }
3727 curproxy->options2 |= PR_O2_EXP_RSTS;
3728 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3729 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3730 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3731 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
3734 }
3735 }
3736 else if (strcmp(ptr_arg, "rstring") == 0) {
3737 if (!*(args[cur_arg + 1])) {
3738 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3739 file, linenum, args[0], args[1], ptr_arg);
3740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
3742 }
3743 curproxy->options2 |= PR_O2_EXP_RSTR;
3744 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3745 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3746 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3747 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
3750 }
3751 }
3752 else {
3753 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3754 file, linenum, args[0], args[1], ptr_arg);
3755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
3757 }
3758 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003759 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003760 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003763 }
3764 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003765 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003766 if (curproxy == &defproxy) {
3767 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003770 }
3771
Willy Tarreaub80c2302007-11-30 20:51:32 +01003772 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003774
3775 if (strcmp(args[1], "fail") == 0) {
3776 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003777 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003778 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3779 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003782 }
3783
Willy Tarreauef6494c2010-01-28 17:12:36 +01003784 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003785 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3786 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003789 }
3790 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3791 }
3792 else {
3793 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003796 }
3797 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798#ifdef TPROXY
3799 else if (!strcmp(args[0], "transparent")) {
3800 /* enable transparent proxy connections */
3801 curproxy->options |= PR_O_TRANSP;
3802 }
3803#endif
3804 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003805 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003807
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 if (*(args[1]) == 0) {
3809 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812 }
3813 curproxy->maxconn = atol(args[1]);
3814 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003815 else if (!strcmp(args[0], "backlog")) { /* backlog */
3816 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003818
3819 if (*(args[1]) == 0) {
3820 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003823 }
3824 curproxy->backlog = atol(args[1]);
3825 }
Willy Tarreau86034312006-12-29 00:10:33 +01003826 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003829
Willy Tarreau86034312006-12-29 00:10:33 +01003830 if (*(args[1]) == 0) {
3831 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003834 }
3835 curproxy->fullconn = atol(args[1]);
3836 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3838 if (*(args[1]) == 0) {
3839 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003843 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3844 if (err) {
3845 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3846 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003849 }
3850 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
3852 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003853 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 if (curproxy == &defproxy) {
3855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\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 Tarreau977b8e42006-12-29 14:19:17 +01003859 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003861
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 if (strchr(args[1], ':') == NULL) {
3863 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003867 sk = str2sa(args[1]);
3868 if (!sk) {
3869 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
3872 }
3873 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003874 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 }
3876 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003877 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003879
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003880 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003881 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3882 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003887 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3888 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3889 err_code |= ERR_WARN;
3890
3891 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3892 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3893 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3894 }
3895 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3896 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3897 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3898 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003899 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3900 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3901 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3902 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003903 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003904 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
3907 }
3908 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003909 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003910 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003911 char *rport, *raddr;
3912 short realport = 0;
3913 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003915 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003916 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", 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 Tarreau977b8e42006-12-29 14:19:17 +01003920 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003922
3923 if (!*args[2]) {
3924 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003929
3930 err = invalid_char(args[1]);
3931 if (err) {
3932 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3933 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003936 }
3937
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003938 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003939 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003940
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003941 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3942 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3943 err_code |= ERR_ALERT | ERR_ABORT;
3944 goto out;
3945 }
3946
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003947 /* the servers are linked backwards first */
3948 newsrv->next = curproxy->srv;
3949 curproxy->srv = newsrv;
3950 newsrv->proxy = curproxy;
3951 newsrv->conf.file = file;
3952 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003954 LIST_INIT(&newsrv->pendconns);
3955 do_check = 0;
3956 newsrv->state = SRV_RUNNING; /* early server setup */
3957 newsrv->last_change = now.tv_sec;
3958 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003960 /* several ways to check the port component :
3961 * - IP => port=+0, relative
3962 * - IP: => port=+0, relative
3963 * - IP:N => port=N, absolute
3964 * - IP:+N => port=+N, relative
3965 * - IP:-N => port=-N, relative
3966 */
3967 raddr = strdup(args[2]);
3968 rport = strchr(raddr, ':');
3969 if (rport) {
3970 *rport++ = 0;
3971 realport = atol(rport);
3972 if (!isdigit((unsigned char)*rport))
3973 newsrv->state |= SRV_MAPPORTS;
3974 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003976
Willy Tarreaud5191e72010-02-09 20:50:45 +01003977 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003978 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003979 if (!sk) {
3980 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
3983 }
3984 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003985
3986 switch (newsrv->addr.ss_family) {
3987 case AF_INET:
3988 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3989 break;
3990 case AF_INET6:
3991 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3992 break;
3993 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003994
3995 newsrv->check_port = curproxy->defsrv.check_port;
3996 newsrv->inter = curproxy->defsrv.inter;
3997 newsrv->fastinter = curproxy->defsrv.fastinter;
3998 newsrv->downinter = curproxy->defsrv.downinter;
3999 newsrv->rise = curproxy->defsrv.rise;
4000 newsrv->fall = curproxy->defsrv.fall;
4001 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4002 newsrv->minconn = curproxy->defsrv.minconn;
4003 newsrv->maxconn = curproxy->defsrv.maxconn;
4004 newsrv->slowstart = curproxy->defsrv.slowstart;
4005 newsrv->onerror = curproxy->defsrv.onerror;
4006 newsrv->consecutive_errors_limit
4007 = curproxy->defsrv.consecutive_errors_limit;
4008 newsrv->uweight = newsrv->iweight
4009 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004011 newsrv->curfd = -1; /* no health-check in progress */
4012 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004014 cur_arg = 3;
4015 } else {
4016 newsrv = &curproxy->defsrv;
4017 cur_arg = 1;
4018 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004019
Willy Tarreaubaaee002006-06-26 02:48:02 +02004020 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004021 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004022 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004023
4024 if (!*args[cur_arg + 1]) {
4025 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4026 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004029 }
4030
4031 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004032 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004033
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004034 if (newsrv->puid <= 0) {
4035 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004036 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004039 }
4040
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004041 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4042 if (node) {
4043 struct server *target = container_of(node, struct server, conf.id);
4044 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4045 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
4049 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004050 cur_arg += 2;
4051 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004052 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 newsrv->cookie = strdup(args[cur_arg + 1]);
4054 newsrv->cklen = strlen(args[cur_arg + 1]);
4055 cur_arg += 2;
4056 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004057 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004058 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4059 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4060 cur_arg += 2;
4061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004063 if (!*args[cur_arg + 1]) {
4064 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4065 file, linenum, args[cur_arg]);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004071 if (newsrv->rise <= 0) {
4072 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4073 file, linenum, args[cur_arg]);
4074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
4076 }
4077
Willy Tarreau96839092010-03-29 10:02:24 +02004078 if (newsrv->health)
4079 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004080 cur_arg += 2;
4081 }
4082 else if (!strcmp(args[cur_arg], "fall")) {
4083 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004084
4085 if (!*args[cur_arg + 1]) {
4086 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4087 file, linenum, args[cur_arg]);
4088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
4090 }
4091
4092 if (newsrv->fall <= 0) {
4093 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4094 file, linenum, args[cur_arg]);
4095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
4097 }
4098
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099 cur_arg += 2;
4100 }
4101 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004102 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 'inter' argument of server %s.\n",
4105 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004108 }
Willy 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 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004115 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004116 cur_arg += 2;
4117 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004118 else if (!strcmp(args[cur_arg], "fastinter")) {
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 'fastinter' 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->fastinter = val;
4133 cur_arg += 2;
4134 }
4135 else if (!strcmp(args[cur_arg], "downinter")) {
4136 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4137 if (err) {
4138 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4139 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004142 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004143 if (val <= 0) {
4144 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4145 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004146 err_code |= ERR_ALERT | ERR_FATAL;
4147 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004148 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004149 newsrv->downinter = val;
4150 cur_arg += 2;
4151 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004152 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004153 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004154 if (!sk) {
4155 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
4158 }
4159 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004160 cur_arg += 2;
4161 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 else if (!strcmp(args[cur_arg], "port")) {
4163 newsrv->check_port = atol(args[cur_arg + 1]);
4164 cur_arg += 2;
4165 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004166 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 newsrv->state |= SRV_BACKUP;
4168 cur_arg ++;
4169 }
4170 else if (!strcmp(args[cur_arg], "weight")) {
4171 int w;
4172 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004173 if (w < 0 || w > 256) {
4174 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004175 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004179 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 cur_arg += 2;
4181 }
4182 else if (!strcmp(args[cur_arg], "minconn")) {
4183 newsrv->minconn = atol(args[cur_arg + 1]);
4184 cur_arg += 2;
4185 }
4186 else if (!strcmp(args[cur_arg], "maxconn")) {
4187 newsrv->maxconn = atol(args[cur_arg + 1]);
4188 cur_arg += 2;
4189 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004190 else if (!strcmp(args[cur_arg], "maxqueue")) {
4191 newsrv->maxqueue = atol(args[cur_arg + 1]);
4192 cur_arg += 2;
4193 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004194 else if (!strcmp(args[cur_arg], "slowstart")) {
4195 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004196 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004197 if (err) {
4198 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4199 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004202 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004203 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004204 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4205 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004208 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004209 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004210 cur_arg += 2;
4211 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004212 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004213
4214 if (!*args[cur_arg + 1]) {
4215 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4216 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004219 }
4220
4221 newsrv->trackit = strdup(args[cur_arg + 1]);
4222
4223 cur_arg += 2;
4224 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004225 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 global.maxsock++;
4227 do_check = 1;
4228 cur_arg += 1;
4229 }
Willy Tarreau96839092010-03-29 10:02:24 +02004230 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4231 newsrv->state |= SRV_MAINTAIN;
4232 newsrv->state &= ~SRV_RUNNING;
4233 newsrv->health = 0;
4234 cur_arg += 1;
4235 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004236 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004237 if (!strcmp(args[cur_arg + 1], "none"))
4238 newsrv->observe = HANA_OBS_NONE;
4239 else if (!strcmp(args[cur_arg + 1], "layer4"))
4240 newsrv->observe = HANA_OBS_LAYER4;
4241 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4242 if (curproxy->mode != PR_MODE_HTTP) {
4243 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4244 file, linenum, args[cur_arg + 1]);
4245 err_code |= ERR_ALERT;
4246 }
4247 newsrv->observe = HANA_OBS_LAYER7;
4248 }
4249 else {
4250 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004251 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004252 file, linenum, args[cur_arg], args[cur_arg + 1]);
4253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
4255 }
4256
4257 cur_arg += 2;
4258 }
4259 else if (!strcmp(args[cur_arg], "on-error")) {
4260 if (!strcmp(args[cur_arg + 1], "fastinter"))
4261 newsrv->onerror = HANA_ONERR_FASTINTER;
4262 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4263 newsrv->onerror = HANA_ONERR_FAILCHK;
4264 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4265 newsrv->onerror = HANA_ONERR_SUDDTH;
4266 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4267 newsrv->onerror = HANA_ONERR_MARKDWN;
4268 else {
4269 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004270 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004271 file, linenum, args[cur_arg], args[cur_arg + 1]);
4272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 }
4275
4276 cur_arg += 2;
4277 }
4278 else if (!strcmp(args[cur_arg], "error-limit")) {
4279 if (!*args[cur_arg + 1]) {
4280 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4281 file, linenum, args[cur_arg]);
4282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
4284 }
4285
4286 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4287
4288 if (newsrv->consecutive_errors_limit <= 0) {
4289 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4290 file, linenum, args[cur_arg]);
4291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
4293 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004294 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004295 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004296 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004297 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004298 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004299
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004301#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004302 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004303 file, linenum, "source", "usesrc");
4304#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004305 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004307#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310 }
4311 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004312 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4313 if (!sk) {
4314 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004319
4320 if (port_low != port_high) {
4321 int i;
4322 if (port_low <= 0 || port_low > 65535 ||
4323 port_high <= 0 || port_high > 65535 ||
4324 port_low > port_high) {
4325 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4326 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004329 }
4330 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4331 for (i = 0; i < newsrv->sport_range->size; i++)
4332 newsrv->sport_range->ports[i] = port_low + i;
4333 }
4334
Willy Tarreaubaaee002006-06-26 02:48:02 +02004335 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004336 while (*(args[cur_arg])) {
4337 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004338#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4339#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004340 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4341 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4342 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004345 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004346#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004347 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004348 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004349 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004352 }
4353 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004354 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004355 newsrv->state |= SRV_TPROXY_CLI;
4356 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004357 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004358 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004359 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4360 char *name, *end;
4361
4362 name = args[cur_arg+1] + 7;
4363 while (isspace(*name))
4364 name++;
4365
4366 end = name;
4367 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4368 end++;
4369
4370 newsrv->state &= ~SRV_TPROXY_MASK;
4371 newsrv->state |= SRV_TPROXY_DYN;
4372 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4373 newsrv->bind_hdr_len = end - name;
4374 memcpy(newsrv->bind_hdr_name, name, end - name);
4375 newsrv->bind_hdr_name[end-name] = '\0';
4376 newsrv->bind_hdr_occ = -1;
4377
4378 /* now look for an occurrence number */
4379 while (isspace(*end))
4380 end++;
4381 if (*end == ',') {
4382 end++;
4383 name = end;
4384 if (*end == '-')
4385 end++;
4386 while (isdigit(*end))
4387 end++;
4388 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4389 }
4390
4391 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4392 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4393 " occurrences values smaller than %d.\n",
4394 file, linenum, MAX_HDR_HISTORY);
4395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
4397 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004398 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004399 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004400 if (!sk) {
4401 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
4404 }
4405 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004406 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004407 }
4408 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004409#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004410 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004411#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004412 cur_arg += 2;
4413 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004414#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004415 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004416 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004419#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4420 } /* "usesrc" */
4421
4422 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4423#ifdef SO_BINDTODEVICE
4424 if (!*args[cur_arg + 1]) {
4425 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4426 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004429 }
4430 if (newsrv->iface_name)
4431 free(newsrv->iface_name);
4432
4433 newsrv->iface_name = strdup(args[cur_arg + 1]);
4434 newsrv->iface_len = strlen(newsrv->iface_name);
4435 global.last_checks |= LSTCHK_NETADM;
4436#else
4437 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4438 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004441#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004442 cur_arg += 2;
4443 continue;
4444 }
4445 /* this keyword in not an option of "source" */
4446 break;
4447 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004449 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004450 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4451 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004455 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004456 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004457 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 +01004458 file, linenum, newsrv->id);
4459 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004460 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 +01004461 file, linenum);
4462
Willy Tarreau93893792009-07-23 13:19:11 +02004463 err_code |= ERR_ALERT | ERR_FATAL;
4464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004465 }
4466 }
4467
4468 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004469 if (newsrv->trackit) {
4470 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4471 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004474 }
4475
David du Colombier6f5ccb12011-03-10 22:26:24 +01004476 switch (newsrv->check_addr.ss_family) {
4477 case AF_INET:
4478 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4479 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4480 break;
4481 case AF_INET6:
4482 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4483 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4484 break;
4485 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004486
Willy Tarreaubaaee002006-06-26 02:48:02 +02004487 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4488 newsrv->check_port = realport; /* by default */
4489 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004490 /* not yet valid, because no port was set on
4491 * the server either. We'll check if we have
4492 * a known port on the first listener.
4493 */
4494 struct listener *l;
4495 l = curproxy->listen;
4496 if (l) {
4497 int port;
4498 port = (l->addr.ss_family == AF_INET6)
4499 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4500 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4501 newsrv->check_port = port;
4502 }
4503 }
4504 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4506 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004510
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004511 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004512 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004513 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4514 err_code |= ERR_ALERT | ERR_ABORT;
4515 goto out;
4516 }
4517
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004518 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004519 newsrv->state |= SRV_CHECKED;
4520 }
4521
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004522 if (!defsrv) {
4523 if (newsrv->state & SRV_BACKUP)
4524 curproxy->srv_bck++;
4525 else
4526 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004527
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004528 newsrv->prev_state = newsrv->state;
4529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 }
4531 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004532 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004533 int facility;
4534
4535 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4536 curproxy->logfac1 = global.logfac1;
4537 curproxy->logsrv1 = global.logsrv1;
4538 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004539 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 curproxy->logfac2 = global.logfac2;
4541 curproxy->logsrv2 = global.logsrv2;
4542 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004543 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 }
4545 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004546 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004547
4548 facility = get_log_facility(args[2]);
4549 if (facility < 0) {
4550 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4551 exit(1);
4552 }
4553
4554 level = 7; /* max syslog level = debug */
4555 if (*(args[3])) {
4556 level = get_log_level(args[3]);
4557 if (level < 0) {
4558 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4559 exit(1);
4560 }
4561 }
4562
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004563 minlvl = 0; /* limit syslog level to this level (emerg) */
4564 if (*(args[4])) {
4565 minlvl = get_log_level(args[4]);
4566 if (level < 0) {
4567 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4568 exit(1);
4569 }
4570 }
4571
Robert Tsai81ae1952007-12-05 10:47:29 +01004572 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004573 struct sockaddr_un *sk = str2sun(args[1]);
4574 if (!sk) {
4575 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4576 args[1], (int)sizeof(sk->sun_path) - 1);
4577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
4579 }
4580 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004581 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004582 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004583 struct sockaddr_storage *sk = str2sa(args[1]);
4584 if (!sk || sk->ss_family != AF_INET) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004585 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
4588 }
David du Colombier6f5ccb12011-03-10 22:26:24 +01004589 logsrv.u.in = *(struct sockaddr_in *)sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004590 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004591 if (!logsrv.u.in.sin_port) {
4592 logsrv.u.in.sin_port =
4593 htons(SYSLOG_PORT);
4594 }
4595 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596
4597 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004598 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004599 curproxy->logfac1 = facility;
4600 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004601 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602 }
4603 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004604 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 curproxy->logfac2 = facility;
4606 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004607 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608 }
4609 else {
4610 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 }
4614 }
4615 else {
4616 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4617 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004620 }
4621 }
4622 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004623 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004624 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004625
Willy Tarreau977b8e42006-12-29 14:19:17 +01004626 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004627 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004628
Willy Tarreaubaaee002006-06-26 02:48:02 +02004629 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004630 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4631 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004635
4636 /* we must first clear any optional default setting */
4637 curproxy->options &= ~PR_O_TPXY_MASK;
4638 free(curproxy->iface_name);
4639 curproxy->iface_name = NULL;
4640 curproxy->iface_len = 0;
4641
Willy Tarreaud5191e72010-02-09 20:50:45 +01004642 sk = str2sa(args[1]);
4643 if (!sk) {
4644 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4645 err_code |= ERR_ALERT | ERR_FATAL;
4646 goto out;
4647 }
4648 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004650
4651 cur_arg = 2;
4652 while (*(args[cur_arg])) {
4653 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004654#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4655#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004656 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4657 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4658 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004661 }
4662#endif
4663 if (!*args[cur_arg + 1]) {
4664 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4665 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004668 }
4669
4670 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004671 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004672 curproxy->options |= PR_O_TPXY_CLI;
4673 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004674 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004675 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004676 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4677 char *name, *end;
4678
4679 name = args[cur_arg+1] + 7;
4680 while (isspace(*name))
4681 name++;
4682
4683 end = name;
4684 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4685 end++;
4686
4687 curproxy->options &= ~PR_O_TPXY_MASK;
4688 curproxy->options |= PR_O_TPXY_DYN;
4689 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4690 curproxy->bind_hdr_len = end - name;
4691 memcpy(curproxy->bind_hdr_name, name, end - name);
4692 curproxy->bind_hdr_name[end-name] = '\0';
4693 curproxy->bind_hdr_occ = -1;
4694
4695 /* now look for an occurrence number */
4696 while (isspace(*end))
4697 end++;
4698 if (*end == ',') {
4699 end++;
4700 name = end;
4701 if (*end == '-')
4702 end++;
4703 while (isdigit(*end))
4704 end++;
4705 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4706 }
4707
4708 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4709 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4710 " occurrences values smaller than %d.\n",
4711 file, linenum, MAX_HDR_HISTORY);
4712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
4714 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004715 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004716 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004717 if (!sk) {
4718 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4719 err_code |= ERR_ALERT | ERR_FATAL;
4720 goto out;
4721 }
4722 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004723 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004724 }
4725 global.last_checks |= LSTCHK_NETADM;
4726#if !defined(CONFIG_HAP_LINUX_TPROXY)
4727 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004728#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004729#else /* no TPROXY support */
4730 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004731 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004734#endif
4735 cur_arg += 2;
4736 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004737 }
4738
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004739 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4740#ifdef SO_BINDTODEVICE
4741 if (!*args[cur_arg + 1]) {
4742 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4743 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004746 }
4747 if (curproxy->iface_name)
4748 free(curproxy->iface_name);
4749
4750 curproxy->iface_name = strdup(args[cur_arg + 1]);
4751 curproxy->iface_len = strlen(curproxy->iface_name);
4752 global.last_checks |= LSTCHK_NETADM;
4753#else
4754 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4755 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004756 err_code |= ERR_ALERT | ERR_FATAL;
4757 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004758#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004759 cur_arg += 2;
4760 continue;
4761 }
4762 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4763 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004768 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4769 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4770 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004774 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004775 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4777 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004780 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004781
4782 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4783 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004784 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004785 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 }
4788 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004789 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4790 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004791 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004792 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 }
4795 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004796 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4797 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004798 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004799 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004801 }
4802 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004803 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4804 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004805 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004806 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004808 }
4809 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004810 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4811 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004812 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004813 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004815 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004816 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004817 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4818 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004819 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004820 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004821 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004822 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004823 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004824 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4825 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004826 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004827 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004828 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004829 }
4830 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004831 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4832 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004833 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004834 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004835 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004836 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004837 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004838 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004839 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4840 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004841 err_code |= ERR_ALERT | ERR_FATAL;
4842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004844
4845 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4846 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004847 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004848 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850 }
4851 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004852 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4853 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004854 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004855 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 }
4858 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004859 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4860 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004861 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004862 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 }
4865 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004866 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4867 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004868 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004869 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
4872 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004873 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4874 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004875 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004876 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004879 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004880 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4881 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004882 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004883 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004884 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004886 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004887 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004888
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889 if (curproxy == &defproxy) {
4890 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004894 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004895 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 if (*(args[1]) == 0) {
4898 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004899 err_code |= ERR_ALERT | ERR_FATAL;
4900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004902
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004903 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4904 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4905 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4906 file, linenum, args[0]);
4907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
4909 }
4910 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4911 }
4912 else if (*args[2]) {
4913 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4914 file, linenum, args[0], args[2]);
4915 err_code |= ERR_ALERT | ERR_FATAL;
4916 goto out;
4917 }
4918
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004919 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004920 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004921 wl->s = strdup(args[1]);
4922 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004923 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 }
4925 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4928 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004932
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4934 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004935 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 }
4939 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4941 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004942 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
4946 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4948 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004949 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4956 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
4960
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4962 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004963 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
4967 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4969 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004970 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004971 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 }
4974 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4976 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004977 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
4981 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004982 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004983
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 if (curproxy == &defproxy) {
4985 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004989 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004990 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992 if (*(args[1]) == 0) {
4993 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 }
4997
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004998 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4999 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
5000 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
5001 file, linenum, args[0]);
5002 err_code |= ERR_ALERT | ERR_FATAL;
5003 goto out;
5004 }
5005 err_code |= warnif_cond_requires_req(cond, file, linenum);
5006 }
5007 else if (*args[2]) {
5008 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5009 file, linenum, args[0], args[2]);
5010 err_code |= ERR_ALERT | ERR_FATAL;
5011 goto out;
5012 }
5013
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005014 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005015 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005016 wl->s = strdup(args[1]);
5017 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 }
5019 else if (!strcmp(args[0], "errorloc") ||
5020 !strcmp(args[0], "errorloc302") ||
5021 !strcmp(args[0], "errorloc303")) { /* error location */
5022 int errnum, errlen;
5023 char *err;
5024
Willy Tarreau977b8e42006-12-29 14:19:17 +01005025 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005027
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005029 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005032 }
5033
5034 errnum = atol(args[1]);
5035 if (!strcmp(args[0], "errorloc303")) {
5036 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5037 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5038 } else {
5039 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5040 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5041 }
5042
Willy Tarreau0f772532006-12-23 20:51:41 +01005043 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5044 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005045 chunk_destroy(&curproxy->errmsg[rc]);
5046 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005047 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005050
5051 if (rc >= HTTP_ERR_SIZE) {
5052 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5053 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 free(err);
5055 }
5056 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005057 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5058 int errnum, errlen, fd;
5059 char *err;
5060 struct stat stat;
5061
5062 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005063 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005064
5065 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005066 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005069 }
5070
5071 fd = open(args[2], O_RDONLY);
5072 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5073 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5074 file, linenum, args[2], args[1]);
5075 if (fd >= 0)
5076 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_ALERT | ERR_FATAL;
5078 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005079 }
5080
Willy Tarreau27a674e2009-08-17 07:23:33 +02005081 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005082 errlen = stat.st_size;
5083 } else {
5084 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005085 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005087 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005088 }
5089
5090 err = malloc(errlen); /* malloc() must succeed during parsing */
5091 errnum = read(fd, err, errlen);
5092 if (errnum != errlen) {
5093 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5094 file, linenum, args[2], args[1]);
5095 close(fd);
5096 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005097 err_code |= ERR_ALERT | ERR_FATAL;
5098 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005099 }
5100 close(fd);
5101
5102 errnum = atol(args[1]);
5103 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5104 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005105 chunk_destroy(&curproxy->errmsg[rc]);
5106 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005107 break;
5108 }
5109 }
5110
5111 if (rc >= HTTP_ERR_SIZE) {
5112 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5113 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005115 free(err);
5116 }
5117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005119 struct cfg_kw_list *kwl;
5120 int index;
5121
5122 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5123 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5124 if (kwl->kw[index].section != CFG_LISTEN)
5125 continue;
5126 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5127 /* prepare error message just in case */
5128 snprintf(trash, sizeof(trash),
5129 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005130 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5131 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005132 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005133 err_code |= ERR_ALERT | ERR_FATAL;
5134 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005135 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005136 else if (rc > 0) {
5137 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_WARN;
5139 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005140 }
Willy Tarreau93893792009-07-23 13:19:11 +02005141 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005142 }
5143 }
5144 }
5145
Willy Tarreau6daf3432008-01-22 16:44:08 +01005146 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 }
Willy Tarreau93893792009-07-23 13:19:11 +02005150 out:
5151 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152}
5153
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005154int
5155cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5156{
5157
5158 int err_code = 0;
5159 const char *err;
5160
5161 if (!strcmp(args[0], "userlist")) { /* new userlist */
5162 struct userlist *newul;
5163
5164 if (!*args[1]) {
5165 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5166 file, linenum, args[0]);
5167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
5169 }
5170
5171 err = invalid_char(args[1]);
5172 if (err) {
5173 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5174 file, linenum, *err, args[0], args[1]);
5175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
5177 }
5178
5179 for (newul = userlist; newul; newul = newul->next)
5180 if (!strcmp(newul->name, args[1])) {
5181 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5182 file, linenum, args[1]);
5183 err_code |= ERR_WARN;
5184 goto out;
5185 }
5186
5187 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5188 if (!newul) {
5189 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5190 err_code |= ERR_ALERT | ERR_ABORT;
5191 goto out;
5192 }
5193
5194 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5195 newul->name = strdup(args[1]);
5196
5197 if (!newul->groupusers | !newul->name) {
5198 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5199 err_code |= ERR_ALERT | ERR_ABORT;
5200 goto out;
5201 }
5202
5203 newul->next = userlist;
5204 userlist = newul;
5205
5206 } else if (!strcmp(args[0], "group")) { /* new group */
5207 int cur_arg, i;
5208 const char *err;
5209
5210 if (!*args[1]) {
5211 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5212 file, linenum, args[0]);
5213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
5215 }
5216
5217 err = invalid_char(args[1]);
5218 if (err) {
5219 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5220 file, linenum, *err, args[0], args[1]);
5221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
5224
5225 for(i = 0; i < userlist->grpcnt; i++)
5226 if (!strcmp(userlist->groups[i], args[1])) {
5227 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5228 file, linenum, args[1], userlist->name);
5229 err_code |= ERR_ALERT;
5230 goto out;
5231 }
5232
5233 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5234 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5235 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5236 err_code |= ERR_ALERT | ERR_FATAL;
5237 goto out;
5238 }
5239
5240 cur_arg = 2;
5241
5242 while (*args[cur_arg]) {
5243 if (!strcmp(args[cur_arg], "users")) {
5244 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5245 cur_arg += 2;
5246 continue;
5247 } else {
5248 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5249 file, linenum, args[0]);
5250 err_code |= ERR_ALERT | ERR_FATAL;
5251 goto out;
5252 }
5253 }
5254
5255 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5256 } else if (!strcmp(args[0], "user")) { /* new user */
5257 struct auth_users *newuser;
5258 int cur_arg;
5259
5260 if (!*args[1]) {
5261 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5262 file, linenum, args[0]);
5263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
5265 }
5266
5267 for (newuser = userlist->users; newuser; newuser = newuser->next)
5268 if (!strcmp(newuser->user, args[1])) {
5269 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5270 file, linenum, args[1], userlist->name);
5271 err_code |= ERR_ALERT;
5272 goto out;
5273 }
5274
5275 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5276 if (!newuser) {
5277 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5278 err_code |= ERR_ALERT | ERR_ABORT;
5279 goto out;
5280 }
5281
5282 newuser->user = strdup(args[1]);
5283
5284 newuser->next = userlist->users;
5285 userlist->users = newuser;
5286
5287 cur_arg = 2;
5288
5289 while (*args[cur_arg]) {
5290 if (!strcmp(args[cur_arg], "password")) {
5291#ifndef CONFIG_HAP_CRYPT
5292 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5293 file, linenum);
5294 err_code |= ERR_ALERT;
5295#endif
5296 newuser->pass = strdup(args[cur_arg + 1]);
5297 cur_arg += 2;
5298 continue;
5299 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5300 newuser->pass = strdup(args[cur_arg + 1]);
5301 newuser->flags |= AU_O_INSECURE;
5302 cur_arg += 2;
5303 continue;
5304 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005305 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005306 cur_arg += 2;
5307 continue;
5308 } else {
5309 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5310 file, linenum, args[0]);
5311 err_code |= ERR_ALERT | ERR_FATAL;
5312 goto out;
5313 }
5314 }
5315 } else {
5316 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5317 err_code |= ERR_ALERT | ERR_FATAL;
5318 }
5319
5320out:
5321 return err_code;
5322}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323
5324/*
5325 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005326 * Returns the error code, 0 if OK, or any combination of :
5327 * - ERR_ABORT: must abort ASAP
5328 * - ERR_FATAL: we can continue parsing but not start the service
5329 * - ERR_WARN: a warning has been emitted
5330 * - ERR_ALERT: an alert has been emitted
5331 * Only the two first ones can stop processing, the two others are just
5332 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005334int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005336 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 FILE *f;
5338 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005339 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005340 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342 if ((f=fopen(file,"r")) == NULL)
5343 return -1;
5344
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005345 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005346 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005347 char *end;
5348 char *args[MAX_LINE_ARGS + 1];
5349 char *line = thisline;
5350
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 linenum++;
5352
5353 end = line + strlen(line);
5354
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005355 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5356 /* Check if we reached the limit and the last char is not \n.
5357 * Watch out for the last line without the terminating '\n'!
5358 */
5359 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005360 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005361 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005362 }
5363
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005365 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 line++;
5367
5368 arg = 0;
5369 args[arg] = line;
5370
5371 while (*line && arg < MAX_LINE_ARGS) {
5372 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5373 * C equivalent value. Other combinations left unchanged (eg: \1).
5374 */
5375 if (*line == '\\') {
5376 int skip = 0;
5377 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5378 *line = line[1];
5379 skip = 1;
5380 }
5381 else if (line[1] == 'r') {
5382 *line = '\r';
5383 skip = 1;
5384 }
5385 else if (line[1] == 'n') {
5386 *line = '\n';
5387 skip = 1;
5388 }
5389 else if (line[1] == 't') {
5390 *line = '\t';
5391 skip = 1;
5392 }
5393 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005394 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005395 unsigned char hex1, hex2;
5396 hex1 = toupper(line[2]) - '0';
5397 hex2 = toupper(line[3]) - '0';
5398 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5399 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5400 *line = (hex1<<4) + hex2;
5401 skip = 3;
5402 }
5403 else {
5404 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005405 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005406 }
5407 }
5408 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005409 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005410 end -= skip;
5411 }
5412 line++;
5413 }
5414 else if (*line == '#' || *line == '\n' || *line == '\r') {
5415 /* end of string, end of loop */
5416 *line = 0;
5417 break;
5418 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005419 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005420 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005421 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005422 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005423 line++;
5424 args[++arg] = line;
5425 }
5426 else {
5427 line++;
5428 }
5429 }
5430
5431 /* empty line */
5432 if (!**args)
5433 continue;
5434
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005435 if (*line) {
5436 /* we had to stop due to too many args.
5437 * Let's terminate the string, print the offending part then cut the
5438 * last arg.
5439 */
5440 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5441 line++;
5442 *line = '\0';
5443
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005444 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005445 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005446 err_code |= ERR_ALERT | ERR_FATAL;
5447 args[arg] = line;
5448 }
5449
Willy Tarreau540abe42007-05-02 20:50:16 +02005450 /* zero out remaining args and ensure that at least one entry
5451 * is zeroed out.
5452 */
5453 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 args[arg] = line;
5455 }
5456
Willy Tarreau3842f002009-06-14 11:39:52 +02005457 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005458 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005459 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005460 for (arg=0; *args[arg+1]; arg++)
5461 args[arg] = args[arg+1]; // shift args after inversion
5462 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005463 else if (!strcmp(args[0], "default")) {
5464 kwm = KWM_DEF;
5465 for (arg=0; *args[arg+1]; arg++)
5466 args[arg] = args[arg+1]; // shift args after inversion
5467 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005468
Willy Tarreau3842f002009-06-14 11:39:52 +02005469 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5470 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005471 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005472 }
5473
Willy Tarreau977b8e42006-12-29 14:19:17 +01005474 if (!strcmp(args[0], "listen") ||
5475 !strcmp(args[0], "frontend") ||
5476 !strcmp(args[0], "backend") ||
5477 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005478 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005480 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005481 cursection = strdup(args[0]);
5482 }
5483 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005485 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005486 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005487 }
5488 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005489 confsect = CFG_USERLIST;
5490 free(cursection);
5491 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005492 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005493 else if (!strcmp(args[0], "peers")) {
5494 confsect = CFG_PEERS;
5495 free(cursection);
5496 cursection = strdup(args[0]);
5497 }
5498
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 /* else it's a section keyword */
5500
5501 switch (confsect) {
5502 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005503 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005504 break;
5505 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005506 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005507 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005508 case CFG_USERLIST:
5509 err_code |= cfg_parse_users(file, linenum, args, kwm);
5510 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005511 case CFG_PEERS:
5512 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5513 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005515 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005516 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005518
5519 if (err_code & ERR_ABORT)
5520 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005522 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005523 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005524 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005525 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005526}
5527
Willy Tarreaubb925012009-07-23 13:36:36 +02005528/*
5529 * Returns the error code, 0 if OK, or any combination of :
5530 * - ERR_ABORT: must abort ASAP
5531 * - ERR_FATAL: we can continue parsing but not start the service
5532 * - ERR_WARN: a warning has been emitted
5533 * - ERR_ALERT: an alert has been emitted
5534 * Only the two first ones can stop processing, the two others are just
5535 * indicators.
5536 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005537int check_config_validity()
5538{
5539 int cfgerr = 0;
5540 struct proxy *curproxy = NULL;
5541 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005542 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005543 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005544 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545
5546 /*
5547 * Now, check for the integrity of all that we have collected.
5548 */
5549
5550 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005551 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005553 /* first, we will invert the proxy list order */
5554 curproxy = NULL;
5555 while (proxy) {
5556 struct proxy *next;
5557
5558 next = proxy->next;
5559 proxy->next = curproxy;
5560 curproxy = proxy;
5561 if (!next)
5562 break;
5563 proxy = next;
5564 }
5565
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005567 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005570 }
5571
5572 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005573 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005574 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005575 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005576 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005577 unsigned int next_id;
5578
5579 if (!curproxy->uuid) {
5580 /* proxy ID not set, use automatic numbering with first
5581 * spare entry starting with next_pxid.
5582 */
5583 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5584 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5585 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005586 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005587 next_pxid++;
5588
Willy Tarreau55ea7572007-06-17 19:56:27 +02005589
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005591 /* ensure we don't keep listeners uselessly bound */
5592 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593 curproxy = curproxy->next;
5594 continue;
5595 }
5596
Willy Tarreauff01a212009-03-15 13:46:16 +01005597 switch (curproxy->mode) {
5598 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005599 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005600 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005601 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5602 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005603 cfgerr++;
5604 }
5605
5606 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005607 Warning("config : servers will be ignored for %s '%s'.\n",
5608 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005609 break;
5610
5611 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005612 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005613 break;
5614
5615 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005616 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005617 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005618 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5619 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005620 cfgerr++;
5621 }
5622 break;
5623 }
5624
5625 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005626 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5627 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 cfgerr++;
5629 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005630
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005631 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005632 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005633 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005634 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5635 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005636 cfgerr++;
5637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005639 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005640 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5641 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005642 cfgerr++;
5643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005644#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005645 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005646 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5647 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005648 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005649 }
5650 }
5651 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005652 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005653 /* If no LB algo is set in a backend, and we're not in
5654 * transparent mode, dispatch mode nor proxy mode, we
5655 * want to use balance roundrobin by default.
5656 */
5657 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5658 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005659 }
5660 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005661
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005662 if (curproxy->options2 & PR_O2_DISPATCH) {
5663 curproxy->options &= ~PR_O_TRANSP;
5664 curproxy->options &= ~PR_O_HTTP_PROXY;
5665 }
5666 else if (curproxy->options & PR_O_HTTP_PROXY) {
5667 curproxy->options2 &= ~PR_O2_DISPATCH;
5668 curproxy->options &= ~PR_O_TRANSP;
5669 }
5670 else if (curproxy->options & PR_O_TRANSP) {
5671 curproxy->options2 &= ~PR_O2_DISPATCH;
5672 curproxy->options &= ~PR_O_HTTP_PROXY;
5673 }
5674
Willy Tarreau82936582007-11-30 15:20:09 +01005675 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5676 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005677 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5678 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005679 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005680 }
5681
Willy Tarreauef781042010-01-27 11:53:01 +01005682 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5683 curproxy->options &= ~PR_O2_CHK_SNDST;
5684 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5685 "send-state", proxy_type_str(curproxy), curproxy->id);
5686 err_code |= ERR_WARN;
5687 }
5688
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005689 /* if a default backend was specified, let's find it */
5690 if (curproxy->defbe.name) {
5691 struct proxy *target;
5692
Alex Williams96532db2009-11-01 21:27:13 -05005693 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005694 if (!target) {
5695 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5696 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005697 cfgerr++;
5698 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005699 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5700 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005701 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005702 } else {
5703 free(curproxy->defbe.name);
5704 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005705 /* we force the backend to be present on at least all of
5706 * the frontend's processes.
5707 */
5708 target->bind_proc = curproxy->bind_proc ?
5709 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 }
5711 }
5712
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005713 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005714 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5715 /* map jump target for ACT_SETBE in req_rep chain */
5716 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005717 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005718 struct proxy *target;
5719
Willy Tarreaua496b602006-12-17 23:15:24 +01005720 if (exp->action != ACT_SETBE)
5721 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005722
Alex Williams96532db2009-11-01 21:27:13 -05005723 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005724 if (!target) {
5725 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5726 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005727 cfgerr++;
5728 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005729 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5730 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005731 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005732 } else {
5733 free((void *)exp->replace);
5734 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005735 /* we force the backend to be present on at least all of
5736 * the frontend's processes.
5737 */
5738 target->bind_proc = curproxy->bind_proc ?
5739 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005740 }
5741 }
5742 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005743
5744 /* find the target proxy for 'use_backend' rules */
5745 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005746 struct proxy *target;
5747
Alex Williams96532db2009-11-01 21:27:13 -05005748 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005749
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005750 if (!target) {
5751 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5752 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005753 cfgerr++;
5754 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005755 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5756 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005757 cfgerr++;
5758 } else {
5759 free((void *)rule->be.name);
5760 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005761 /* we force the backend to be present on at least all of
5762 * the frontend's processes.
5763 */
5764 target->bind_proc = curproxy->bind_proc ?
5765 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005766 }
5767 }
5768
Emeric Brunb982a3d2010-01-04 15:45:53 +01005769 /* find the target table for 'stick' rules */
5770 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5771 struct proxy *target;
5772
Emeric Brun1d33b292010-01-04 15:47:17 +01005773 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5774 if (mrule->flags & STK_IS_STORE)
5775 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5776
Emeric Brunb982a3d2010-01-04 15:45:53 +01005777 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005778 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005779 else
5780 target = curproxy;
5781
5782 if (!target) {
5783 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5784 curproxy->id, mrule->table.name);
5785 cfgerr++;
5786 }
5787 else if (target->table.size == 0) {
5788 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5789 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5790 cfgerr++;
5791 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005792 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005793 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5794 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5795 cfgerr++;
5796 }
5797 else {
5798 free((void *)mrule->table.name);
5799 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005800 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005801 }
5802 }
5803
5804 /* find the target table for 'store response' rules */
5805 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5806 struct proxy *target;
5807
Emeric Brun1d33b292010-01-04 15:47:17 +01005808 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5809
Emeric Brunb982a3d2010-01-04 15:45:53 +01005810 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005811 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005812 else
5813 target = curproxy;
5814
5815 if (!target) {
5816 Alert("Proxy '%s': unable to find store table '%s'.\n",
5817 curproxy->id, mrule->table.name);
5818 cfgerr++;
5819 }
5820 else if (target->table.size == 0) {
5821 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5822 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5823 cfgerr++;
5824 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005825 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005826 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5827 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5828 cfgerr++;
5829 }
5830 else {
5831 free((void *)mrule->table.name);
5832 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005833 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005834 }
5835 }
5836
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005837 /* find the target table for 'tcp-request' layer 4 rules */
5838 list_for_each_entry(trule, &curproxy->tcp_req.l4_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 Tarreau9ba2dcc2010-06-14 21:04:55 +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 Tarreau9ba2dcc2010-06-14 21:04:55 +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 Tarreau9ba2dcc2010-06-14 21:04:55 +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 Tarreau9ba2dcc2010-06-14 21:04:55 +02005869 * to pass a list of counters to track and allocate them right here using
5870 * stktable_alloc_data_type().
5871 */
5872 }
5873 }
5874
Willy Tarreaud1f96522010-08-03 19:34:32 +02005875 /* find the target table for 'tcp-request' layer 6 rules */
5876 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5877 struct proxy *target;
5878
Willy Tarreau56123282010-08-06 19:06:56 +02005879 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005880 continue;
5881
5882 if (trule->act_prm.trk_ctr.table.n)
5883 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5884 else
5885 target = curproxy;
5886
5887 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005888 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5889 curproxy->id, trule->act_prm.trk_ctr.table.n,
5890 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005891 cfgerr++;
5892 }
5893 else if (target->table.size == 0) {
5894 Alert("Proxy '%s': table '%s' used but not configured.\n",
5895 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5896 cfgerr++;
5897 }
5898 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005899 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 +02005900 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5901 cfgerr++;
5902 }
5903 else {
5904 free(trule->act_prm.trk_ctr.table.n);
5905 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005906 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005907 * to pass a list of counters to track and allocate them right here using
5908 * stktable_alloc_data_type().
5909 */
5910 }
5911 }
5912
Emeric Brun32da3c42010-09-23 18:39:19 +02005913 if (curproxy->table.peers.name) {
5914 struct peers *curpeers = peers;
5915
5916 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5917 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5918 free((void *)curproxy->table.peers.name);
5919 curproxy->table.peers.p = peers;
5920 break;
5921 }
5922 }
5923
5924 if (!curpeers) {
5925 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5926 curproxy->id, curproxy->table.peers.name);
5927 cfgerr++;
5928 }
5929 else if (!curpeers->peers_fe) {
5930 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5931 curproxy->id, curpeers->id);
5932 cfgerr++;
5933 }
5934 }
5935
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005936 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005937 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005938 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5939 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5940 "proxy", curproxy->id);
5941 cfgerr++;
5942 goto out_uri_auth_compat;
5943 }
5944
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005945 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005946 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005947 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005948 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005949
Willy Tarreau95fa4692010-02-01 13:05:50 +01005950 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5951 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005952
5953 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005954 uri_auth_compat_req[i++] = "realm";
5955 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5956 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005957
Willy Tarreau95fa4692010-02-01 13:05:50 +01005958 uri_auth_compat_req[i++] = "unless";
5959 uri_auth_compat_req[i++] = "{";
5960 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5961 uri_auth_compat_req[i++] = "}";
5962 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005963
Willy Tarreauff011f22011-01-06 17:51:27 +01005964 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5965 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005966 cfgerr++;
5967 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005968 }
5969
Willy Tarreauff011f22011-01-06 17:51:27 +01005970 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005971
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005972 if (curproxy->uri_auth->auth_realm) {
5973 free(curproxy->uri_auth->auth_realm);
5974 curproxy->uri_auth->auth_realm = NULL;
5975 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005976
5977 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005978 }
5979out_uri_auth_compat:
5980
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005981 cfgerr += acl_find_targets(curproxy);
5982
Willy Tarreau2738a142006-07-08 17:28:09 +02005983 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005984 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005985 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005986 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005987 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005988 " | While not properly invalid, you will certainly encounter various problems\n"
5989 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005990 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005991 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005992 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005993 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005994
Willy Tarreau1fa31262007-12-03 00:36:16 +01005995 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5996 * We must still support older configurations, so let's find out whether those
5997 * parameters have been set or must be copied from contimeouts.
5998 */
5999 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006000 if (!curproxy->timeout.tarpit ||
6001 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006002 /* tarpit timeout not set. We search in the following order:
6003 * default.tarpit, curr.connect, default.connect.
6004 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006005 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006006 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006007 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006008 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006009 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006010 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006011 }
6012 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006013 (!curproxy->timeout.queue ||
6014 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006015 /* queue timeout not set. We search in the following order:
6016 * default.queue, curr.connect, default.connect.
6017 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006018 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006019 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006020 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006021 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006022 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006023 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006024 }
6025 }
6026
Willy Tarreau07a54902010-03-29 18:33:29 +02006027 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006028 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6029 curproxy->check_req = (char *)malloc(curproxy->check_len);
6030 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006031 }
6032
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006033 /* The small pools required for the capture lists */
6034 if (curproxy->nb_req_cap)
6035 curproxy->req_cap_pool = create_pool("ptrcap",
6036 curproxy->nb_req_cap * sizeof(char *),
6037 MEM_F_SHARED);
6038 if (curproxy->nb_rsp_cap)
6039 curproxy->rsp_cap_pool = create_pool("ptrcap",
6040 curproxy->nb_rsp_cap * sizeof(char *),
6041 MEM_F_SHARED);
6042
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006043 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6044 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6045 MEM_F_SHARED);
6046
Willy Tarreau86034312006-12-29 00:10:33 +01006047 /* for backwards compatibility with "listen" instances, if
6048 * fullconn is not set but maxconn is set, then maxconn
6049 * is used.
6050 */
6051 if (!curproxy->fullconn)
6052 curproxy->fullconn = curproxy->maxconn;
6053
Willy Tarreaubaaee002006-06-26 02:48:02 +02006054 /* first, we will invert the servers list order */
6055 newsrv = NULL;
6056 while (curproxy->srv) {
6057 struct server *next;
6058
6059 next = curproxy->srv->next;
6060 curproxy->srv->next = newsrv;
6061 newsrv = curproxy->srv;
6062 if (!next)
6063 break;
6064 curproxy->srv = next;
6065 }
6066
Willy Tarreaudd701652010-05-25 23:03:02 +02006067 /* assign automatic UIDs to servers which don't have one yet */
6068 next_id = 1;
6069 newsrv = curproxy->srv;
6070 while (newsrv != NULL) {
6071 if (!newsrv->puid) {
6072 /* server ID not set, use automatic numbering with first
6073 * spare entry starting with next_svid.
6074 */
6075 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6076 newsrv->conf.id.key = newsrv->puid = next_id;
6077 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6078 }
6079 next_id++;
6080 newsrv = newsrv->next;
6081 }
6082
Willy Tarreau20697042007-11-15 23:26:18 +01006083 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006084 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006085
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006086 /* We have to initialize the server lookup mechanism depending
6087 * on what LB algorithm was choosen.
6088 */
6089
6090 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6091 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6092 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006093 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6094 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6095 init_server_map(curproxy);
6096 } else {
6097 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6098 fwrr_init_server_groups(curproxy);
6099 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006100 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006101
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006102 case BE_LB_KIND_LC:
6103 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006104 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006105 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006106
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006107 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006108 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6109 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6110 chash_init_server_tree(curproxy);
6111 } else {
6112 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6113 init_server_map(curproxy);
6114 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006115 break;
6116 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006117
6118 if (curproxy->options & PR_O_LOGASAP)
6119 curproxy->to_log &= ~LW_BYTES;
6120
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006121 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6122 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6123 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6124 proxy_type_str(curproxy), curproxy->id);
6125 err_code |= ERR_WARN;
6126 }
6127
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006128 if (curproxy->mode != PR_MODE_HTTP) {
6129 int optnum;
6130
6131 if (curproxy->options & PR_O_COOK_ANY) {
6132 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6133 proxy_type_str(curproxy), curproxy->id);
6134 err_code |= ERR_WARN;
6135 }
6136
6137 if (curproxy->uri_auth) {
6138 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6139 proxy_type_str(curproxy), curproxy->id);
6140 err_code |= ERR_WARN;
6141 curproxy->uri_auth = NULL;
6142 }
6143
6144 if (curproxy->options & PR_O_FWDFOR) {
6145 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6146 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6147 err_code |= ERR_WARN;
6148 curproxy->options &= ~PR_O_FWDFOR;
6149 }
6150
6151 if (curproxy->options & PR_O_ORGTO) {
6152 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6153 "originalto", proxy_type_str(curproxy), curproxy->id);
6154 err_code |= ERR_WARN;
6155 curproxy->options &= ~PR_O_ORGTO;
6156 }
6157
6158 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6159 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6160 (curproxy->cap & cfg_opts[optnum].cap) &&
6161 (curproxy->options & cfg_opts[optnum].val)) {
6162 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6163 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6164 err_code |= ERR_WARN;
6165 curproxy->options &= ~cfg_opts[optnum].val;
6166 }
6167 }
6168
6169 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6170 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6171 (curproxy->cap & cfg_opts2[optnum].cap) &&
6172 (curproxy->options2 & cfg_opts2[optnum].val)) {
6173 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6174 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6175 err_code |= ERR_WARN;
6176 curproxy->options2 &= ~cfg_opts2[optnum].val;
6177 }
6178 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006179
Willy Tarreauefa5f512010-03-30 20:13:29 +02006180#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006181 if (curproxy->bind_hdr_occ) {
6182 curproxy->bind_hdr_occ = 0;
6183 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6184 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6185 err_code |= ERR_WARN;
6186 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006187#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006188 }
6189
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006191 * ensure that we're not cross-dressing a TCP server into HTTP.
6192 */
6193 newsrv = curproxy->srv;
6194 while (newsrv != NULL) {
6195 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006196 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6197 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006198 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006199 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006200
Willy Tarreauefa5f512010-03-30 20:13:29 +02006201#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006202 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6203 newsrv->bind_hdr_occ = 0;
6204 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6205 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6206 err_code |= ERR_WARN;
6207 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006208#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006209 newsrv = newsrv->next;
6210 }
6211
6212 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006213 * If this server supports a maxconn parameter, it needs a dedicated
6214 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006215 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216 */
6217 newsrv = curproxy->srv;
6218 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006219 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006220 /* Only 'minconn' was specified, or it was higher than or equal
6221 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6222 * this will avoid further useless expensive computations.
6223 */
6224 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006225 } else if (newsrv->maxconn && !newsrv->minconn) {
6226 /* minconn was not specified, so we set it to maxconn */
6227 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006228 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006229 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6230 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006231 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006232 }
6233
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006234 if (newsrv->trackit) {
6235 struct proxy *px;
6236 struct server *srv;
6237 char *pname, *sname;
6238
6239 pname = newsrv->trackit;
6240 sname = strrchr(pname, '/');
6241
6242 if (sname)
6243 *sname++ = '\0';
6244 else {
6245 sname = pname;
6246 pname = NULL;
6247 }
6248
6249 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006250 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006251 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006252 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6253 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006254 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006255 cfgerr++;
6256 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006257 }
6258 } else
6259 px = curproxy;
6260
6261 srv = findserver(px, sname);
6262 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006263 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6264 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006265 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006266 cfgerr++;
6267 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006268 }
6269
6270 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006271 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006272 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006273 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006274 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006275 cfgerr++;
6276 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006277 }
6278
6279 if (curproxy != px &&
6280 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006281 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006282 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006283 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006284 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006285 cfgerr++;
6286 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006287 }
6288
6289 newsrv->tracked = srv;
6290 newsrv->tracknext = srv->tracknext;
6291 srv->tracknext = newsrv;
6292
6293 free(newsrv->trackit);
6294 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006295 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006296 newsrv = newsrv->next;
6297 }
6298
Willy Tarreauc1a21672009-08-16 22:37:44 +02006299 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006300 curproxy->accept = frontend_accept;
6301
Willy Tarreauc1a21672009-08-16 22:37:44 +02006302 if (curproxy->tcp_req.inspect_delay ||
6303 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006304 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006305
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006306 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006307 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006308 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006309 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006310
6311 /* both TCP and HTTP must check switching rules */
6312 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6313 }
6314
6315 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006316 if (curproxy->tcp_req.inspect_delay ||
6317 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6318 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6319
Emeric Brun97679e72010-09-23 17:56:44 +02006320 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6321 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6322
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006323 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006324 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006325 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006326 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006327
6328 /* If the backend does requires RDP cookie persistence, we have to
6329 * enable the corresponding analyser.
6330 */
6331 if (curproxy->options2 & PR_O2_RDPC_PRST)
6332 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6333 }
6334
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006335 listener = NULL;
6336 while (curproxy->listen) {
6337 struct listener *next;
6338
6339 next = curproxy->listen->next;
6340 curproxy->listen->next = listener;
6341 listener = curproxy->listen;
6342
6343 if (!next)
6344 break;
6345
6346 curproxy->listen = next;
6347 }
6348
Willy Tarreaue6b98942007-10-29 01:09:36 +01006349 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006350 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006351 listener = curproxy->listen;
6352 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006353 if (!listener->luid) {
6354 /* listener ID not set, use automatic numbering with first
6355 * spare entry starting with next_luid.
6356 */
6357 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6358 listener->conf.id.key = listener->luid = next_id;
6359 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006360 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006361 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006362
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006363 /* enable separate counters */
6364 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6365 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6366 if (!listener->name) {
6367 sprintf(trash, "sock-%d", listener->luid);
6368 listener->name = strdup(trash);
6369 }
6370 }
6371
Willy Tarreaue6b98942007-10-29 01:09:36 +01006372 if (curproxy->options & PR_O_TCP_NOLING)
6373 listener->options |= LI_O_NOLINGER;
6374 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006375 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006376 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006377 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006378 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006379 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006380 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006381
Willy Tarreau8a956912010-10-15 14:27:08 +02006382 if (listener->options & LI_O_ACC_PROXY)
6383 listener->analysers |= AN_REQ_DECODE_PROXY;
6384
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006385 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6386 listener->options |= LI_O_TCP_RULES;
6387
Willy Tarreaude3041d2010-05-31 10:56:17 +02006388 if (curproxy->mon_mask.s_addr)
6389 listener->options |= LI_O_CHK_MONNET;
6390
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006391 /* smart accept mode is automatic in HTTP mode */
6392 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6393 (curproxy->mode == PR_MODE_HTTP &&
6394 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6395 listener->options |= LI_O_NOQUICKACK;
6396
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006397 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006398 listener = listener->next;
6399 }
6400
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006401 /* Check multi-process mode compatibility for the current proxy */
6402 if (global.nbproc > 1) {
6403 int nbproc = 0;
6404 if (curproxy->bind_proc) {
6405 int proc;
6406 for (proc = 0; proc < global.nbproc; proc++) {
6407 if (curproxy->bind_proc & (1 << proc)) {
6408 nbproc++;
6409 }
6410 }
6411 } else {
6412 nbproc = global.nbproc;
6413 }
6414 if (curproxy->table.peers.name) {
6415 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6416 curproxy->id);
6417 cfgerr++;
6418 }
6419 if (nbproc > 1) {
6420 if (curproxy->uri_auth) {
6421 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6422 curproxy->id);
6423 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6424 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6425 curproxy->id);
6426 }
6427 }
6428 if (curproxy->appsession_name) {
6429 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6430 curproxy->id);
6431 }
6432 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6433 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6434 curproxy->id);
6435 }
6436 }
6437 }
6438
Willy Tarreaubaaee002006-06-26 02:48:02 +02006439 curproxy = curproxy->next;
6440 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006441
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006442 /* Check multi-process mode compatibility */
6443 if (global.nbproc > 1) {
6444 if (global.stats_fe) {
6445 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6446 }
6447 }
6448
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006449 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6450 struct auth_users *curuser;
6451 int g;
6452
6453 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6454 unsigned int group_mask = 0;
6455 char *group = NULL;
6456
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006457 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006458 continue;
6459
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006460 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006461
6462 for (g = 0; g < curuserlist->grpcnt; g++)
6463 if (!strcmp(curuserlist->groups[g], group))
6464 break;
6465
6466 if (g == curuserlist->grpcnt) {
6467 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6468 curuserlist->name, group, curuser->user);
6469 err_code |= ERR_ALERT | ERR_FATAL;
6470 goto out;
6471 }
6472
6473 group_mask |= (1 << g);
6474 }
6475
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006476 free(curuser->u.groups);
6477 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006478 }
6479
6480 for (g = 0; g < curuserlist->grpcnt; g++) {
6481 char *user = NULL;
6482
6483 if (!curuserlist->groupusers[g])
6484 continue;
6485
6486 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6487 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6488 if (!strcmp(curuser->user, user))
6489 break;
6490
6491 if (!curuser) {
6492 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6493 curuserlist->name, user, curuserlist->groups[g]);
6494 err_code |= ERR_ALERT | ERR_FATAL;
6495 goto out;
6496 }
6497
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006498 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006499 }
6500
6501 free(curuserlist->groupusers[g]);
6502 }
6503
6504 free(curuserlist->groupusers);
6505
6506#ifdef DEBUG_AUTH
6507 for (g = 0; g < curuserlist->grpcnt; g++) {
6508 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6509
6510 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6511 if (curuser->group_mask & (1 << g))
6512 fprintf(stderr, " %s", curuser->user);
6513 }
6514
6515 fprintf(stderr, "\n");
6516 }
6517#endif
6518
6519 }
6520
Willy Tarreau056f5682010-06-06 15:51:11 +02006521 /* initialize stick-tables on backend capable proxies. This must not
6522 * be done earlier because the data size may be discovered while parsing
6523 * other proxies.
6524 */
6525 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006526 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006527
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006528 /*
6529 * Recount currently required checks.
6530 */
6531
6532 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6533 int optnum;
6534
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006535 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6536 if (curproxy->options & cfg_opts[optnum].val)
6537 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006538
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006539 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6540 if (curproxy->options2 & cfg_opts2[optnum].val)
6541 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006542 }
6543
Willy Tarreaubb925012009-07-23 13:36:36 +02006544 if (cfgerr > 0)
6545 err_code |= ERR_ALERT | ERR_FATAL;
6546 out:
6547 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006548}
6549
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006550/*
6551 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6552 * parsing sessions.
6553 */
6554void cfg_register_keywords(struct cfg_kw_list *kwl)
6555{
6556 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6557}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006558
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006559/*
6560 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6561 */
6562void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6563{
6564 LIST_DEL(&kwl->list);
6565 LIST_INIT(&kwl->list);
6566}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006567
6568/*
6569 * Local variables:
6570 * c-indent-level: 8
6571 * c-basic-offset: 8
6572 * End:
6573 */