blob: aeec87ba2a7fff22758e490bab9639eac328b90c [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010047#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010053#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010062#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010064#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065
66
Willy Tarreauf3c69202006-07-09 16:42:34 +020067/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
68 * ssl-hello-chk option to ensure that the remote server speaks SSL.
69 *
70 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
71 */
72const char sslv3_client_hello_pkt[] = {
73 "\x16" /* ContentType : 0x16 = Hanshake */
74 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
75 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
76 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
77 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
78 "\x03\x00" /* Hello Version : 0x0300 = v3 */
79 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
80 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
81 "\x00" /* Session ID length : empty (no session ID) */
82 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
83 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
84 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
85 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
86 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
87 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
88 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
89 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
90 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
91 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
92 "\x00\x38" "\x00\x39" "\x00\x3A"
93 "\x01" /* Compression Length : 0x01 = 1 byte for types */
94 "\x00" /* Compression Type : 0x00 = NULL compression */
95};
96
Willy Tarreau3842f002009-06-14 11:39:52 +020097/* various keyword modifiers */
98enum kw_mod {
99 KWM_STD = 0, /* normal */
100 KWM_NO, /* "no" prefixed before the keyword */
101 KWM_DEF, /* "default" prefixed before the keyword */
102};
103
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106 const char *name;
107 unsigned int val;
108 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100110 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111};
112
113/* proxy->options */
114static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
117 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
118 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
119 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
120 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
121 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
122 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
126 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
128 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
129 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
130 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
131 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100132#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100134#else
135 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100136#endif
137
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139};
140
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100141/* proxy->options2 */
142static const struct cfg_opt cfg_opts2[] =
143{
144#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100148#else
149 { "splice-request", 0, 0, 0, 0 },
150 { "splice-response", 0, 0, 0, 0 },
151 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
154 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
155 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
156 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
157 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
158 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
161 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
162 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200163 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200186static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
189 char *c, *next, *range, *dupstr;
190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
210 Alert("Socket path '%s' too long (max %d)\n", str, max_path_len);
211 goto fail;
212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200215 ss.ss_family = AF_UNIX;
216 if (global.unix_bind.prefix) {
217 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
218 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 }
Emeric Bruned760922010-10-22 17:59:25 +0200220 else {
221 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
222 }
223 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 }
225 else {
Emeric Bruned760922010-10-22 17:59:25 +0200226 /* 2) look for the addr/port delimiter, it's the last colon. */
227 if ((range = strrchr(str, ':')) == NULL) {
228 Alert("Missing port number: '%s'\n", str);
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 }
Emeric Bruned760922010-10-22 17:59:25 +0200231
232 *range++ = 0;
233
234 if (strrchr(str, ':') != NULL) {
235 /* IPv6 address contains ':' */
236 memset(&ss, 0, sizeof(ss));
237 ss.ss_family = AF_INET6;
238
239 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
240 Alert("Invalid server address: '%s'\n", str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Emeric Bruned760922010-10-22 17:59:25 +0200244 else {
245 memset(&ss, 0, sizeof(ss));
246 ss.ss_family = AF_INET;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Emeric Bruned760922010-10-22 17:59:25 +0200248 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
249 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
250 }
251 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
252 struct hostent *he;
253
254 if ((he = gethostbyname(str)) == NULL) {
255 Alert("Invalid server name: '%s'\n", str);
256 goto fail;
257 }
258 else
259 ((struct sockaddr_in *)&ss)->sin_addr =
260 *(struct in_addr *) *(he->h_addr_list);
261 }
262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
Emeric Bruned760922010-10-22 17:59:25 +0200264 /* 3) look for the port-end delimiter */
265 if ((c = strchr(range, '-')) != NULL) {
266 *c++ = 0;
267 end = atol(c);
268 }
269 else {
270 end = atol(range);
271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272
Emeric Bruned760922010-10-22 17:59:25 +0200273 port = atol(range);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
Emeric Bruned760922010-10-22 17:59:25 +0200275 if (port < 1 || port > 65535) {
276 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
277 goto fail;
278 }
279
280 if (end < 1 || end > 65535) {
281 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
282 goto fail;
283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 }
285
286 for (; port <= end; port++) {
287 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200288 l->next = curproxy->listen;
289 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290
291 l->fd = -1;
292 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 l->state = LI_INIT;
294
Emeric Bruned760922010-10-22 17:59:25 +0200295 if(ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100297 tcpv4_add_listener(l);
298 }
Emeric Bruned760922010-10-22 17:59:25 +0200299 else if (ss.ss_family == AF_INET6) {
300 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
301 tcpv6_add_listener(l);
302 }
303 else {
304 l->perm.ux.gid = l->perm.ux.uid = -1;
305 l->perm.ux.mode = 0;
306 uxst_add_listener(l);
307 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200308
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200309 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100310 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311 } /* end for(port) */
312 } /* end while(next) */
313 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 fail:
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318}
319
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320/*
321 * Sends a warning if proxy <proxy> does not have at least one of the
322 * capabilities in <cap>. An optionnal <hint> may be added at the end
323 * of the warning to help the user. Returns 1 if a warning was emitted
324 * or 0 if the condition is valid.
325 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100326int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100327{
328 char *msg;
329
330 switch (cap) {
331 case PR_CAP_BE: msg = "no backend"; break;
332 case PR_CAP_FE: msg = "no frontend"; break;
333 case PR_CAP_RS: msg = "no ruleset"; break;
334 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
335 default: msg = "not enough"; break;
336 }
337
338 if (!(proxy->cap & cap)) {
339 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100340 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100341 return 1;
342 }
343 return 0;
344}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200345
Willy Tarreau61d18892009-03-31 10:49:21 +0200346/* Report a warning if a rule is placed after a 'block' rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
351 if (!LIST_ISEMPTY(&proxy->block_cond)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a reqrewrite rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (proxy->req_exp) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a reqadd rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100377 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* Report a warning if a rule is placed after a redirect rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
398/* Report a warning if a rule is placed after a 'use_backend' rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
411/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
415 warnif_rule_after_reqadd(proxy, file, line, arg) ||
416 warnif_rule_after_redirect(proxy, file, line, arg) ||
417 warnif_rule_after_use_backend(proxy, file, line, arg);
418}
419
420/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100421int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200422{
423 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
424 warnif_rule_after_redirect(proxy, file, line, arg) ||
425 warnif_rule_after_use_backend(proxy, file, line, arg);
426}
427
428/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
431 return warnif_rule_after_redirect(proxy, file, line, arg) ||
432 warnif_rule_after_use_backend(proxy, file, line, arg);
433}
434
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100435/* Report it if a request ACL condition uses some response-only parameters. It
436 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
447 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100452/* Report it if a request ACL condition uses some request-only volatile parameters.
453 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
454 * Note that <cond> may be NULL and then will be ignored.
455 */
456static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
457{
458 struct acl *acl;
459
460 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
461 return 0;
462
463 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
464 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
465 file, line, acl ? acl->name : "(unknown)");
466 return ERR_WARN;
467}
468
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100469
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200471 * parse a line in a <global> section. Returns the error code, 0 if OK, or
472 * any combination of :
473 * - ERR_ABORT: must abort ASAP
474 * - ERR_FATAL: we can continue parsing but not start the service
475 * - ERR_WARN: a warning has been emitted
476 * - ERR_ALERT: an alert has been emitted
477 * Only the two first ones can stop processing, the two others are just
478 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200480int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481{
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483
484 if (!strcmp(args[0], "global")) { /* new section */
485 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487 }
488 else if (!strcmp(args[0], "daemon")) {
489 global.mode |= MODE_DAEMON;
490 }
491 else if (!strcmp(args[0], "debug")) {
492 global.mode |= MODE_DEBUG;
493 }
494 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100495 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200496 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200497 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100498 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200499 }
500 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100501 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100504 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100506 else if (!strcmp(args[0], "nosplice")) {
507 global.tune.options &= ~GTUNE_USE_SPLICE;
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "quiet")) {
510 global.mode |= MODE_QUIET;
511 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200512 else if (!strcmp(args[0], "tune.maxpollevents")) {
513 if (global.tune.maxpollevents != 0) {
514 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200515 err_code |= ERR_ALERT;
516 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200517 }
518 if (*(args[1]) == 0) {
519 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200520 err_code |= ERR_ALERT | ERR_FATAL;
521 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200522 }
523 global.tune.maxpollevents = atol(args[1]);
524 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100525 else if (!strcmp(args[0], "tune.maxaccept")) {
526 if (global.tune.maxaccept != 0) {
527 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200528 err_code |= ERR_ALERT;
529 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100530 }
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100535 }
536 global.tune.maxaccept = atol(args[1]);
537 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200538 else if (!strcmp(args[0], "tune.chksize")) {
539 if (*(args[1]) == 0) {
540 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT | ERR_FATAL;
542 goto out;
543 }
544 global.tune.chksize = atol(args[1]);
545 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200546 else if (!strcmp(args[0], "tune.bufsize")) {
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.bufsize = atol(args[1]);
553 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
554 global.tune.maxrewrite = global.tune.bufsize / 2;
555 }
556 else if (!strcmp(args[0], "tune.maxrewrite")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.maxrewrite = atol(args[1]);
563 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
564 global.tune.maxrewrite = global.tune.bufsize / 2;
565 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100566 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
567 if (global.tune.client_rcvbuf != 0) {
568 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT;
570 goto out;
571 }
572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
576 }
577 global.tune.client_rcvbuf = atol(args[1]);
578 }
579 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
580 if (global.tune.server_rcvbuf != 0) {
581 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT;
583 goto out;
584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.server_rcvbuf = atol(args[1]);
591 }
592 else if (!strcmp(args[0], "tune.sndbuf.client")) {
593 if (global.tune.client_sndbuf != 0) {
594 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT;
596 goto out;
597 }
598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 global.tune.client_sndbuf = atol(args[1]);
604 }
605 else if (!strcmp(args[0], "tune.sndbuf.server")) {
606 if (global.tune.server_sndbuf != 0) {
607 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT;
609 goto out;
610 }
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.server_sndbuf = atol(args[1]);
617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 else if (!strcmp(args[0], "uid")) {
619 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624 if (*(args[1]) == 0) {
625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 }
629 global.uid = atol(args[1]);
630 }
631 else if (!strcmp(args[0], "gid")) {
632 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 }
642 global.gid = atol(args[1]);
643 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 /* user/group name handling */
645 else if (!strcmp(args[0], "user")) {
646 struct passwd *ha_user;
647 if (global.uid != 0) {
648 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200649 err_code |= ERR_ALERT;
650 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200651 }
652 errno = 0;
653 ha_user = getpwnam(args[1]);
654 if (ha_user != NULL) {
655 global.uid = (int)ha_user->pw_uid;
656 }
657 else {
658 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200660 }
661 }
662 else if (!strcmp(args[0], "group")) {
663 struct group *ha_group;
664 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200665 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200666 err_code |= ERR_ALERT;
667 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 errno = 0;
670 ha_group = getgrnam(args[1]);
671 if (ha_group != NULL) {
672 global.gid = (int)ha_group->gr_gid;
673 }
674 else {
675 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200677 }
678 }
679 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 else if (!strcmp(args[0], "nbproc")) {
681 if (global.nbproc != 0) {
682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 }
691 global.nbproc = atol(args[1]);
692 }
693 else if (!strcmp(args[0], "maxconn")) {
694 if (global.maxconn != 0) {
695 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 global.maxconn = atol(args[1]);
705#ifdef SYSTEM_MAXCONN
706 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
707 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
708 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 }
711#endif /* SYSTEM_MAXCONN */
712 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100713 else if (!strcmp(args[0], "maxpipes")) {
714 if (global.maxpipes != 0) {
715 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200716 err_code |= ERR_ALERT;
717 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100718 }
719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100723 }
724 global.maxpipes = atol(args[1]);
725 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 else if (!strcmp(args[0], "ulimit-n")) {
727 if (global.rlimit_nofile != 0) {
728 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT;
730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 }
732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 }
737 global.rlimit_nofile = atol(args[1]);
738 }
739 else if (!strcmp(args[0], "chroot")) {
740 if (global.chroot != NULL) {
741 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200742 err_code |= ERR_ALERT;
743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 }
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 global.chroot = strdup(args[1]);
751 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200752 else if (!strcmp(args[0], "description")) {
753 int i, len=0;
754 char *d;
755
756 if (!*args[1]) {
757 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
758 file, linenum, args[0]);
759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
761 }
762
763 for(i=1; *args[i]; i++)
764 len += strlen(args[i])+1;
765
766 if (global.desc)
767 free(global.desc);
768
769 global.desc = d = (char *)calloc(1, len);
770
771 d += sprintf(d, "%s", args[1]);
772 for(i=2; *args[i]; i++)
773 d += sprintf(d, " %s", args[i]);
774 }
775 else if (!strcmp(args[0], "node")) {
776 int i;
777 char c;
778
779 for (i=0; args[1][i]; i++) {
780 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100781 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
782 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200783 break;
784 }
785
786 if (!i || args[1][i]) {
787 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
788 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
789 file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
793
794 if (global.node)
795 free(global.node);
796
797 global.node = strdup(args[1]);
798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 else if (!strcmp(args[0], "pidfile")) {
800 if (global.pidfile != NULL) {
801 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200802 err_code |= ERR_ALERT;
803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 }
810 global.pidfile = strdup(args[1]);
811 }
Emeric Bruned760922010-10-22 17:59:25 +0200812 else if (!strcmp(args[0], "unix-bind")) {
813 int cur_arg = 1;
814 while (*(args[cur_arg])) {
815 if (!strcmp(args[cur_arg], "prefix")) {
816 if (global.unix_bind.prefix != NULL) {
817 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
818 err_code |= ERR_ALERT;
819 cur_arg += 2;
820 continue;
821 }
822
823 if (*(args[cur_arg+1]) == 0) {
824 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.unix_bind.prefix = strdup(args[cur_arg+1]);
829 cur_arg += 2;
830 continue;
831 }
832
833 if (!strcmp(args[cur_arg], "mode")) {
834
835 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
836 cur_arg += 2;
837 continue;
838 }
839
840 if (!strcmp(args[cur_arg], "uid")) {
841
842 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
843 cur_arg += 2;
844 continue;
845 }
846
847 if (!strcmp(args[cur_arg], "gid")) {
848
849 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
850 cur_arg += 2;
851 continue;
852 }
853
854 if (!strcmp(args[cur_arg], "user")) {
855 struct passwd *user;
856
857 user = getpwnam(args[cur_arg + 1]);
858 if (!user) {
859 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
860 file, linenum, args[0], args[cur_arg + 1 ]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864
865 global.unix_bind.ux.uid = user->pw_uid;
866 cur_arg += 2;
867 continue;
868 }
869
870 if (!strcmp(args[cur_arg], "group")) {
871 struct group *group;
872
873 group = getgrnam(args[cur_arg + 1]);
874 if (!group) {
875 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
876 file, linenum, args[0], args[cur_arg + 1 ]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880
881 global.unix_bind.ux.gid = group->gr_gid;
882 cur_arg += 2;
883 continue;
884 }
885
886 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
887 file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100893 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200894 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895
896 if (*(args[1]) == 0 || *(args[2]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901
902 facility = get_log_facility(args[2]);
903 if (facility < 0) {
904 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200905 err_code |= ERR_ALERT | ERR_FATAL;
906 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200907 }
908
909 level = 7; /* max syslog level = debug */
910 if (*(args[3])) {
911 level = get_log_level(args[3]);
912 if (level < 0) {
913 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200914 err_code |= ERR_ALERT | ERR_FATAL;
915 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 }
917 }
918
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200919 minlvl = 0; /* limit syslog level to this level (emerg) */
920 if (*(args[4])) {
921 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200923 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT | ERR_FATAL;
925 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 }
927 }
928
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100930 struct sockaddr_un *sk = str2sun(args[1]);
931 if (!sk) {
932 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
933 args[1], (int)sizeof(sk->sun_path) - 1);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100938 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100939 } else {
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);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001061 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001062 LIST_INIT(&p->block_cond);
1063 LIST_INIT(&p->redirect_rules);
1064 LIST_INIT(&p->mon_fail_cond);
1065 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001066 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001067 LIST_INIT(&p->sticking_rules);
1068 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001069 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001070 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001071 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001072 LIST_INIT(&p->req_add);
1073 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001074
1075 /* Timeouts are defined as -1 */
1076 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001077 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001078}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001080void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001082 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 defproxy.mode = PR_MODE_TCP;
1084 defproxy.state = PR_STNEW;
1085 defproxy.maxconn = cfg_maxpconn;
1086 defproxy.conn_retries = CONN_RETRIES;
1087 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001088
1089 defproxy.defsrv.inter = DEF_CHKINTR;
1090 defproxy.defsrv.fastinter = 0;
1091 defproxy.defsrv.downinter = 0;
1092 defproxy.defsrv.rise = DEF_RISETIME;
1093 defproxy.defsrv.fall = DEF_FALLTIME;
1094 defproxy.defsrv.check_port = 0;
1095 defproxy.defsrv.maxqueue = 0;
1096 defproxy.defsrv.minconn = 0;
1097 defproxy.defsrv.maxconn = 0;
1098 defproxy.defsrv.slowstart = 0;
1099 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1100 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1101 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102}
1103
Willy Tarreauade5ec42010-01-28 19:33:49 +01001104
1105static int create_cond_regex_rule(const char *file, int line,
1106 struct proxy *px, int dir, int action, int flags,
1107 const char *cmd, const char *reg, const char *repl,
1108 const char **cond_start)
1109{
1110 regex_t *preg = NULL;
1111 const char *err;
1112 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001113 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001114
1115 if (px == &defproxy) {
1116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1117 err_code |= ERR_ALERT | ERR_FATAL;
1118 goto err;
1119 }
1120
1121 if (*reg == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
1127 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1128 err_code |= ERR_WARN;
1129
Willy Tarreau5321c422010-01-28 20:35:13 +01001130 if (cond_start &&
1131 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1132 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1133 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1134 file, line, cmd);
1135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto err;
1137 }
1138 }
1139 else if (cond_start && **cond_start) {
1140 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1141 file, line, cmd, *cond_start);
1142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto err;
1144 }
1145
1146 if (dir == ACL_DIR_REQ)
1147 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001148 else
1149 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001150
Willy Tarreauade5ec42010-01-28 19:33:49 +01001151 preg = calloc(1, sizeof(regex_t));
1152 if (!preg) {
1153 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1154 err_code = ERR_ALERT | ERR_FATAL;
1155 goto err;
1156 }
1157
1158 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1159 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1160 err_code = ERR_ALERT | ERR_FATAL;
1161 goto err;
1162 }
1163
1164 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001165 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001166 if (repl && err) {
1167 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1168 file, line, cmd, *err);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto err;
1171 }
1172
1173 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1174 err_code |= ERR_WARN;
1175
1176 return err_code;
1177 err:
1178 free(preg);
1179 return err_code;
1180}
1181
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001183 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001184 * Returns the error code, 0 if OK, or any combination of :
1185 * - ERR_ABORT: must abort ASAP
1186 * - ERR_FATAL: we can continue parsing but not start the service
1187 * - ERR_WARN: a warning has been emitted
1188 * - ERR_ALERT: an alert has been emitted
1189 * Only the two first ones can stop processing, the two others are just
1190 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001192int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1193{
1194 static struct peers *curpeers = NULL;
1195 struct peer *newpeer = NULL;
1196 const char *err;
1197 int err_code = 0;
1198
1199 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1200
1201 err = invalid_char(args[1]);
1202 if (err) {
1203 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1204 file, linenum, *err, args[0], args[1]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 }
1207
1208 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1209 /*
1210 * If there are two proxies with the same name only following
1211 * combinations are allowed:
1212 */
1213 if (strcmp(curpeers->id, args[1]) == 0) {
1214 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1215 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1216 err_code |= ERR_WARN;
1217 }
1218 }
1219
1220 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1221 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1222 err_code |= ERR_ALERT | ERR_ABORT;
1223 goto out;
1224 }
1225
1226 curpeers->next = peers;
1227 peers = curpeers;
1228 curpeers->conf.file = file;
1229 curpeers->conf.line = linenum;
1230 curpeers->last_change = now.tv_sec;
1231 curpeers->id = strdup(args[1]);
1232 }
1233 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1234 char *rport, *raddr;
1235 short realport = 0;
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 */
2465 struct req_acl_rule *req_acl;
2466
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
2473
2474 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2475 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2476 file, linenum, args[0]);
2477 err_code |= ERR_WARN;
2478 }
2479
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002480 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002481
2482 if (!req_acl) {
2483 err_code |= ERR_ALERT | ERR_ABORT;
2484 goto out;
2485 }
2486
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002487 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002488 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2489 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002490 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002491 if (curproxy == &defproxy) {
2492 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002495 }
2496
Willy Tarreauef6494c2010-01-28 17:12:36 +01002497 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002498 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2499 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002502 }
2503
Willy Tarreauef6494c2010-01-28 17:12:36 +01002504 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002505 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2506 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002509 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002510
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002511 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002512 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002513 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002514 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002515 struct redirect_rule *rule;
2516 int cur_arg;
2517 int type = REDIRECT_TYPE_NONE;
2518 int code = 302;
2519 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002520 char *cookie = NULL;
2521 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002522 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002523
Cyril Bonté99ed3272010-01-24 23:29:44 +01002524 if (curproxy == &defproxy) {
2525 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
2528 }
2529
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002530 cur_arg = 1;
2531 while (*(args[cur_arg])) {
2532 if (!strcmp(args[cur_arg], "location")) {
2533 if (!*args[cur_arg + 1]) {
2534 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2535 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002538 }
2539
2540 type = REDIRECT_TYPE_LOCATION;
2541 cur_arg++;
2542 destination = args[cur_arg];
2543 }
2544 else if (!strcmp(args[cur_arg], "prefix")) {
2545 if (!*args[cur_arg + 1]) {
2546 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2547 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_FATAL;
2549 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002550 }
2551
2552 type = REDIRECT_TYPE_PREFIX;
2553 cur_arg++;
2554 destination = args[cur_arg];
2555 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002556 else if (!strcmp(args[cur_arg], "set-cookie")) {
2557 if (!*args[cur_arg + 1]) {
2558 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2559 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002562 }
2563
2564 cur_arg++;
2565 cookie = args[cur_arg];
2566 cookie_set = 1;
2567 }
2568 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2569 if (!*args[cur_arg + 1]) {
2570 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2571 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002574 }
2575
2576 cur_arg++;
2577 cookie = args[cur_arg];
2578 cookie_set = 0;
2579 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002580 else if (!strcmp(args[cur_arg],"code")) {
2581 if (!*args[cur_arg + 1]) {
2582 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2583 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002586 }
2587 cur_arg++;
2588 code = atol(args[cur_arg]);
2589 if (code < 301 || code > 303) {
2590 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2591 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002592 err_code |= ERR_ALERT | ERR_FATAL;
2593 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002594 }
2595 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002596 else if (!strcmp(args[cur_arg],"drop-query")) {
2597 flags |= REDIRECT_FLAG_DROP_QS;
2598 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002599 else if (!strcmp(args[cur_arg],"append-slash")) {
2600 flags |= REDIRECT_FLAG_APPEND_SLASH;
2601 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002602 else if (strcmp(args[cur_arg], "if") == 0 ||
2603 strcmp(args[cur_arg], "unless") == 0) {
2604 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2605 if (!cond) {
2606 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2607 file, linenum, args[0]);
2608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
2610 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002611 break;
2612 }
2613 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002614 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 +02002615 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002616 err_code |= ERR_ALERT | ERR_FATAL;
2617 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002618 }
2619 cur_arg++;
2620 }
2621
2622 if (type == REDIRECT_TYPE_NONE) {
2623 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2624 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002625 err_code |= ERR_ALERT | ERR_FATAL;
2626 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002627 }
2628
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002629 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2630 rule->cond = cond;
2631 rule->rdr_str = strdup(destination);
2632 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002633 if (cookie) {
2634 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002635 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002636 */
2637 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002638 if (cookie_set) {
2639 rule->cookie_str = malloc(rule->cookie_len + 10);
2640 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2641 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2642 rule->cookie_len += 9;
2643 } else {
2644 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002645 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002646 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2647 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002648 }
2649 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002650 rule->type = type;
2651 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002652 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002653 LIST_INIT(&rule->list);
2654 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002655 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2656 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002657 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002658 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002659 struct switching_rule *rule;
2660
Willy Tarreaub099aca2008-10-12 17:26:37 +02002661 if (curproxy == &defproxy) {
2662 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002665 }
2666
Willy Tarreau55ea7572007-06-17 19:56:27 +02002667 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002668 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002669
2670 if (*(args[1]) == 0) {
2671 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002674 }
2675
Willy Tarreauef6494c2010-01-28 17:12:36 +01002676 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002677 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2678 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002681 }
2682
Willy Tarreauef6494c2010-01-28 17:12:36 +01002683 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002684 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002685 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002688 }
2689
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002690 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002691
Willy Tarreau55ea7572007-06-17 19:56:27 +02002692 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2693 rule->cond = cond;
2694 rule->be.name = strdup(args[1]);
2695 LIST_INIT(&rule->list);
2696 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2697 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002698 else if ((!strcmp(args[0], "force-persist")) ||
2699 (!strcmp(args[0], "ignore-persist"))) {
2700 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002701
2702 if (curproxy == &defproxy) {
2703 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
2706 }
2707
2708 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2709 err_code |= ERR_WARN;
2710
Willy Tarreauef6494c2010-01-28 17:12:36 +01002711 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002712 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2713 file, linenum, args[0]);
2714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
2716 }
2717
Willy Tarreauef6494c2010-01-28 17:12:36 +01002718 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002719 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2720 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
2723 }
2724
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002725 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002726
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002727 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002728 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002729 if (!strcmp(args[0], "force-persist")) {
2730 rule->type = PERSIST_TYPE_FORCE;
2731 } else {
2732 rule->type = PERSIST_TYPE_IGNORE;
2733 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002734 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002735 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002736 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002737 else if (!strcmp(args[0], "stick-table")) {
2738 int myidx = 1;
2739
Emeric Brun32da3c42010-09-23 18:39:19 +02002740 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002741 curproxy->table.type = (unsigned int)-1;
2742 while (*args[myidx]) {
2743 const char *err;
2744
2745 if (strcmp(args[myidx], "size") == 0) {
2746 myidx++;
2747 if (!*(args[myidx])) {
2748 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2749 file, linenum, args[myidx-1]);
2750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
2752 }
2753 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2754 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2755 file, linenum, *err, args[myidx-1]);
2756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
2758 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002759 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002760 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002761 else if (strcmp(args[myidx], "peers") == 0) {
2762 myidx++;
2763 if (!*(args[myidx])) {
2764 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2765 file, linenum, args[myidx-1]);
2766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769 curproxy->table.peers.name = strdup(args[myidx++]);
2770 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002771 else if (strcmp(args[myidx], "expire") == 0) {
2772 myidx++;
2773 if (!*(args[myidx])) {
2774 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2775 file, linenum, args[myidx-1]);
2776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
2778 }
2779 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2780 if (err) {
2781 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2782 file, linenum, *err, args[myidx-1]);
2783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
2785 }
2786 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002787 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002788 }
2789 else if (strcmp(args[myidx], "nopurge") == 0) {
2790 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002791 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002792 }
2793 else if (strcmp(args[myidx], "type") == 0) {
2794 myidx++;
2795 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2796 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2797 file, linenum, args[myidx]);
2798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
2800 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002801 /* myidx already points to next arg */
2802 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002803 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002804 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002805 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002806
2807 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002808 nw = args[myidx];
2809 while (*nw) {
2810 /* the "store" keyword supports a comma-separated list */
2811 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002812 sa = NULL; /* store arg */
2813 while (*nw && *nw != ',') {
2814 if (*nw == '(') {
2815 *nw = 0;
2816 sa = ++nw;
2817 while (*nw != ')') {
2818 if (!*nw) {
2819 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2820 file, linenum, args[0], cw);
2821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
2823 }
2824 nw++;
2825 }
2826 *nw = '\0';
2827 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002828 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002829 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002830 if (*nw)
2831 *nw++ = '\0';
2832 type = stktable_get_data_type(cw);
2833 if (type < 0) {
2834 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2835 file, linenum, args[0], cw);
2836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
2838 }
Willy Tarreauac782882010-06-20 10:41:54 +02002839
2840 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2841 switch (err) {
2842 case PE_NONE: break;
2843 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002844 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2845 file, linenum, args[0], cw);
2846 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002847 break;
2848
2849 case PE_ARG_MISSING:
2850 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2851 file, linenum, args[0], cw);
2852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
2854
2855 case PE_ARG_NOT_USED:
2856 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2857 file, linenum, args[0], cw);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860
2861 default:
2862 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2863 file, linenum, args[0], cw);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002866 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002867 }
2868 myidx++;
2869 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002870 else {
2871 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2872 file, linenum, args[myidx]);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002875 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002876 }
2877
2878 if (!curproxy->table.size) {
2879 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2880 file, linenum);
2881 err_code |= ERR_ALERT | ERR_FATAL;
2882 goto out;
2883 }
2884
2885 if (curproxy->table.type == (unsigned int)-1) {
2886 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2887 file, linenum);
2888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
2891 }
2892 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002893 struct sticking_rule *rule;
2894 struct pattern_expr *expr;
2895 int myidx = 0;
2896 const char *name = NULL;
2897 int flags;
2898
2899 if (curproxy == &defproxy) {
2900 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
2903 }
2904
2905 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2906 err_code |= ERR_WARN;
2907 goto out;
2908 }
2909
2910 myidx++;
2911 if ((strcmp(args[myidx], "store") == 0) ||
2912 (strcmp(args[myidx], "store-request") == 0)) {
2913 myidx++;
2914 flags = STK_IS_STORE;
2915 }
2916 else if (strcmp(args[myidx], "store-response") == 0) {
2917 myidx++;
2918 flags = STK_IS_STORE | STK_ON_RSP;
2919 }
2920 else if (strcmp(args[myidx], "match") == 0) {
2921 myidx++;
2922 flags = STK_IS_MATCH;
2923 }
2924 else if (strcmp(args[myidx], "on") == 0) {
2925 myidx++;
2926 flags = STK_IS_MATCH | STK_IS_STORE;
2927 }
2928 else {
2929 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933
2934 if (*(args[myidx]) == 0) {
2935 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938 }
2939
Emeric Brun485479d2010-09-23 18:02:19 +02002940 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002941 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002942 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946
2947 if (flags & STK_ON_RSP) {
2948 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2949 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2950 file, linenum, args[0], expr->fetch->kw);
2951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
2953 }
2954 } else {
2955 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2956 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2957 file, linenum, args[0], expr->fetch->kw);
2958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
2960 }
2961 }
2962
2963 if (strcmp(args[myidx], "table") == 0) {
2964 myidx++;
2965 name = args[myidx++];
2966 }
2967
Willy Tarreauef6494c2010-01-28 17:12:36 +01002968 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2969 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002970 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2971 file, linenum, args[0]);
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002975 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002976 else if (*(args[myidx])) {
2977 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2978 file, linenum, args[0], args[myidx]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
Emeric Brun97679e72010-09-23 17:56:44 +02002982 if (flags & STK_ON_RSP)
2983 err_code |= warnif_cond_requires_req(cond, file, linenum);
2984 else
2985 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002986
Emeric Brunb982a3d2010-01-04 15:45:53 +01002987 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2988 rule->cond = cond;
2989 rule->expr = expr;
2990 rule->flags = flags;
2991 rule->table.name = name ? strdup(name) : NULL;
2992 LIST_INIT(&rule->list);
2993 if (flags & STK_ON_RSP)
2994 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2995 else
2996 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002999 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003000 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003001
Willy Tarreaubaaee002006-06-26 02:48:02 +02003002 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3003 curproxy->uri_auth = NULL; /* we must detach from the default config */
3004
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003005 if (!*args[1]) {
3006 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003007 } else if (!strcmp(args[1], "admin")) {
3008 struct stats_admin_rule *rule;
3009
3010 if (curproxy == &defproxy) {
3011 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
3014 }
3015
3016 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3017 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3018 err_code |= ERR_ALERT | ERR_ABORT;
3019 goto out;
3020 }
3021
3022 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3023 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3024 file, linenum, args[0], args[1]);
3025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
3027 }
3028 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3029 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3030 file, linenum, args[0], args[1]);
3031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
3033 }
3034
3035 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3036
3037 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3038 rule->cond = cond;
3039 LIST_INIT(&rule->list);
3040 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 } else if (!strcmp(args[1], "uri")) {
3042 if (*(args[2]) == 0) {
3043 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3047 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_ABORT;
3049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 }
3051 } else if (!strcmp(args[1], "realm")) {
3052 if (*(args[2]) == 0) {
3053 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3057 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_ABORT;
3059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003061 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003062 unsigned interval;
3063
3064 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3065 if (err) {
3066 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3067 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003070 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3071 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_ABORT;
3073 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003074 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003075 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
3076 struct req_acl_rule *req_acl;
3077
3078 if (curproxy == &defproxy) {
3079 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
3082 }
3083
3084 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3085 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3086 err_code |= ERR_ALERT | ERR_ABORT;
3087 goto out;
3088 }
3089
3090 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
3091 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
3092 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3093 file, linenum, args[0]);
3094 err_code |= ERR_WARN;
3095 }
3096
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003097 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003098
3099 if (!req_acl) {
3100 err_code |= ERR_ALERT | ERR_ABORT;
3101 goto out;
3102 }
3103
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003104 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003105 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
3106
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 } else if (!strcmp(args[1], "auth")) {
3108 if (*(args[2]) == 0) {
3109 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3113 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_ABORT;
3115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 }
3117 } else if (!strcmp(args[1], "scope")) {
3118 if (*(args[2]) == 0) {
3119 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3123 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_ALERT | ERR_ABORT;
3125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 }
3127 } else if (!strcmp(args[1], "enable")) {
3128 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3129 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_ALERT | ERR_ABORT;
3131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003133 } else if (!strcmp(args[1], "hide-version")) {
3134 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3135 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003136 err_code |= ERR_ALERT | ERR_ABORT;
3137 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003138 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003139 } else if (!strcmp(args[1], "show-legends")) {
3140 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3141 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3142 err_code |= ERR_ALERT | ERR_ABORT;
3143 goto out;
3144 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003145 } else if (!strcmp(args[1], "show-node")) {
3146
3147 if (*args[2]) {
3148 int i;
3149 char c;
3150
3151 for (i=0; args[2][i]; i++) {
3152 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003153 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3154 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003155 break;
3156 }
3157
3158 if (!i || args[2][i]) {
3159 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3160 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3161 file, linenum, args[0], args[1]);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
3164 }
3165 }
3166
3167 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3168 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3169 err_code |= ERR_ALERT | ERR_ABORT;
3170 goto out;
3171 }
3172 } else if (!strcmp(args[1], "show-desc")) {
3173 char *desc = NULL;
3174
3175 if (*args[2]) {
3176 int i, len=0;
3177 char *d;
3178
3179 for(i=2; *args[i]; i++)
3180 len += strlen(args[i])+1;
3181
3182 desc = d = (char *)calloc(1, len);
3183
3184 d += sprintf(d, "%s", args[2]);
3185 for(i=3; *args[i]; i++)
3186 d += sprintf(d, " %s", args[i]);
3187 }
3188
3189 if (!*args[2] && !global.desc)
3190 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3191 file, linenum, args[1]);
3192 else {
3193 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3194 free(desc);
3195 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3196 err_code |= ERR_ALERT | ERR_ABORT;
3197 goto out;
3198 }
3199 free(desc);
3200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003202stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003203 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 +01003204 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 }
3208 }
3209 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003210 int optnum;
3211
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003212 if (*(args[1]) == '\0') {
3213 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3214 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003218
3219 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3220 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003221 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3222 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3223 file, linenum, cfg_opts[optnum].name);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
Willy Tarreau93893792009-07-23 13:19:11 +02003227 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3228 err_code |= ERR_WARN;
3229 goto out;
3230 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003231
Willy Tarreau3842f002009-06-14 11:39:52 +02003232 curproxy->no_options &= ~cfg_opts[optnum].val;
3233 curproxy->options &= ~cfg_opts[optnum].val;
3234
3235 switch (kwm) {
3236 case KWM_STD:
3237 curproxy->options |= cfg_opts[optnum].val;
3238 break;
3239 case KWM_NO:
3240 curproxy->no_options |= cfg_opts[optnum].val;
3241 break;
3242 case KWM_DEF: /* already cleared */
3243 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003244 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003245
Willy Tarreau93893792009-07-23 13:19:11 +02003246 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003247 }
3248 }
3249
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003250 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3251 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003252 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3253 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3254 file, linenum, cfg_opts2[optnum].name);
3255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
3257 }
Willy Tarreau93893792009-07-23 13:19:11 +02003258 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3259 err_code |= ERR_WARN;
3260 goto out;
3261 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003262
Willy Tarreau3842f002009-06-14 11:39:52 +02003263 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3264 curproxy->options2 &= ~cfg_opts2[optnum].val;
3265
3266 switch (kwm) {
3267 case KWM_STD:
3268 curproxy->options2 |= cfg_opts2[optnum].val;
3269 break;
3270 case KWM_NO:
3271 curproxy->no_options2 |= cfg_opts2[optnum].val;
3272 break;
3273 case KWM_DEF: /* already cleared */
3274 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003275 }
Willy Tarreau93893792009-07-23 13:19:11 +02003276 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003277 }
3278 }
3279
Willy Tarreau3842f002009-06-14 11:39:52 +02003280 if (kwm != KWM_STD) {
3281 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003282 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003285 }
3286
Emeric Brun3a058f32009-06-30 18:26:00 +02003287 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003289 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003291 if (*(args[2]) != '\0') {
3292 if (!strcmp(args[2], "clf")) {
3293 curproxy->options2 |= PR_O2_CLFLOG;
3294 } else {
3295 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003298 }
3299 }
3300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 else if (!strcmp(args[1], "tcplog"))
3302 /* generate a detailed TCP log */
3303 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 else if (!strcmp(args[1], "tcpka")) {
3305 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003306 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003308
3309 if (curproxy->cap & PR_CAP_FE)
3310 curproxy->options |= PR_O_TCP_CLI_KA;
3311 if (curproxy->cap & PR_CAP_BE)
3312 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 }
3314 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003315 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_WARN;
3317
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003319 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003320 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003321 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003322 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003323 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003324 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003325 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003326 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 if (!*args[2]) { /* no argument */
3328 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3329 curproxy->check_len = strlen(DEF_CHECK_REQ);
3330 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003331 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 curproxy->check_req = (char *)malloc(reqlen);
3333 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003334 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003336 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 if (*args[4])
3338 reqlen += strlen(args[4]);
3339 else
3340 reqlen += strlen("HTTP/1.0");
3341
3342 curproxy->check_req = (char *)malloc(reqlen);
3343 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003344 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003346 }
3347 else if (!strcmp(args[1], "ssl-hello-chk")) {
3348 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003349 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003351
Willy Tarreaua534fea2008-08-03 12:19:50 +02003352 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003353 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003354 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003355 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003356 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003357 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003358 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003359 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 }
Willy Tarreau23677902007-05-08 23:50:35 +02003361 else if (!strcmp(args[1], "smtpchk")) {
3362 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003363 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003364 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003365 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003366 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003367 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003368 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003369 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003370 curproxy->options |= PR_O_SMTP_CHK;
3371
3372 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3373 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3374 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3375 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3376 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3377 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3378 curproxy->check_req = (char *)malloc(reqlen);
3379 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3380 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3381 } else {
3382 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3383 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3384 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3385 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3386 }
3387 }
3388 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003389 else if (!strcmp(args[1], "pgsql-check")) {
3390 /* use PostgreSQL request to check servers' health */
3391 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3392 err_code |= ERR_WARN;
3393
3394 free(curproxy->check_req);
3395 curproxy->check_req = NULL;
3396 curproxy->options &= ~PR_O_HTTP_CHK;
3397 curproxy->options &= ~PR_O_SMTP_CHK;
3398 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3399 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3400 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3401 curproxy->options2 |= PR_O2_PGSQL_CHK;
3402
3403 if (*(args[2])) {
3404 int cur_arg = 2;
3405
3406 while (*(args[cur_arg])) {
3407 if (strcmp(args[cur_arg], "user") == 0) {
3408 char * packet;
3409 uint32_t packet_len;
3410 uint32_t pv;
3411
3412 /* suboption header - needs additional argument for it */
3413 if (*(args[cur_arg+1]) == 0) {
3414 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3415 file, linenum, args[0], args[1], args[cur_arg]);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419
3420 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3421 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3422 pv = htonl(0x30000); /* protocol version 3.0 */
3423
3424 packet = (char*) calloc(1, packet_len);
3425
3426 memcpy(packet + 4, &pv, 4);
3427
3428 /* copy "user" */
3429 memcpy(packet + 8, "user", 4);
3430
3431 /* copy username */
3432 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3433
3434 free(curproxy->check_req);
3435 curproxy->check_req = packet;
3436 curproxy->check_len = packet_len;
3437
3438 packet_len = htonl(packet_len);
3439 memcpy(packet, &packet_len, 4);
3440 cur_arg += 2;
3441 } else {
3442 /* unknown suboption - catchall */
3443 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3444 file, linenum, args[0], args[1]);
3445 err_code |= ERR_ALERT | ERR_FATAL;
3446 goto out;
3447 }
3448 } /* end while loop */
3449 }
3450 }
3451
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003452 else if (!strcmp(args[1], "mysql-check")) {
3453 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003454 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3455 err_code |= ERR_WARN;
3456
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003457 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003458 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003459 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003460 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003461 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003462 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003463 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003464 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003465
3466 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3467 * const char mysql40_client_auth_pkt[] = {
3468 * "\x0e\x00\x00" // packet length
3469 * "\x01" // packet number
3470 * "\x00\x00" // client capabilities
3471 * "\x00\x00\x01" // max packet
3472 * "haproxy\x00" // username (null terminated string)
3473 * "\x00" // filler (always 0x00)
3474 * "\x01\x00\x00" // packet length
3475 * "\x00" // packet number
3476 * "\x01" // COM_QUIT command
3477 * };
3478 */
3479
3480 if (*(args[2])) {
3481 int cur_arg = 2;
3482
3483 while (*(args[cur_arg])) {
3484 if (strcmp(args[cur_arg], "user") == 0) {
3485 char *mysqluser;
3486 int packetlen, reqlen, userlen;
3487
3488 /* suboption header - needs additional argument for it */
3489 if (*(args[cur_arg+1]) == 0) {
3490 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3491 file, linenum, args[0], args[1], args[cur_arg]);
3492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
3494 }
3495 mysqluser = args[cur_arg + 1];
3496 userlen = strlen(mysqluser);
3497 packetlen = userlen + 7;
3498 reqlen = packetlen + 9;
3499
3500 free(curproxy->check_req);
3501 curproxy->check_req = (char *)calloc(1, reqlen);
3502 curproxy->check_len = reqlen;
3503
3504 snprintf(curproxy->check_req, 4, "%c%c%c",
3505 ((unsigned char) packetlen & 0xff),
3506 ((unsigned char) (packetlen >> 8) & 0xff),
3507 ((unsigned char) (packetlen >> 16) & 0xff));
3508
3509 curproxy->check_req[3] = 1;
3510 curproxy->check_req[8] = 1;
3511 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3512 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3513 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3514 cur_arg += 2;
3515 } else {
3516 /* unknown suboption - catchall */
3517 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3518 file, linenum, args[0], args[1]);
3519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
3521 }
3522 } /* end while loop */
3523 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003524 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003525 else if (!strcmp(args[1], "ldap-check")) {
3526 /* use LDAP request to check servers' health */
3527 free(curproxy->check_req);
3528 curproxy->check_req = NULL;
3529 curproxy->options &= ~PR_O_HTTP_CHK;
3530 curproxy->options &= ~PR_O_SMTP_CHK;
3531 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3532 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003533 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003534 curproxy->options2 |= PR_O2_LDAP_CHK;
3535
3536 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3537 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3538 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3539 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003540 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003541 int cur_arg;
3542
3543 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3544 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003545 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003546
3547 curproxy->options |= PR_O_FWDFOR;
3548
3549 free(curproxy->fwdfor_hdr_name);
3550 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3551 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3552
3553 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3554 cur_arg = 2;
3555 while (*(args[cur_arg])) {
3556 if (!strcmp(args[cur_arg], "except")) {
3557 /* suboption except - needs additional argument for it */
3558 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3559 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3560 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003563 }
3564 /* flush useless bits */
3565 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003566 cur_arg += 2;
3567 } else if (!strcmp(args[cur_arg], "header")) {
3568 /* suboption header - needs additional argument for it */
3569 if (*(args[cur_arg+1]) == 0) {
3570 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3571 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003574 }
3575 free(curproxy->fwdfor_hdr_name);
3576 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3577 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3578 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003579 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003580 /* unknown suboption - catchall */
3581 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3582 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003583 err_code |= ERR_ALERT | ERR_FATAL;
3584 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003585 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003586 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003587 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003588 else if (!strcmp(args[1], "originalto")) {
3589 int cur_arg;
3590
3591 /* insert x-original-to field, but not for the IP address listed as an except.
3592 * set default options (ie: bitfield, header name, etc)
3593 */
3594
3595 curproxy->options |= PR_O_ORGTO;
3596
3597 free(curproxy->orgto_hdr_name);
3598 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3599 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3600
3601 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3602 cur_arg = 2;
3603 while (*(args[cur_arg])) {
3604 if (!strcmp(args[cur_arg], "except")) {
3605 /* suboption except - needs additional argument for it */
3606 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3607 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3608 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003609 err_code |= ERR_ALERT | ERR_FATAL;
3610 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003611 }
3612 /* flush useless bits */
3613 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3614 cur_arg += 2;
3615 } else if (!strcmp(args[cur_arg], "header")) {
3616 /* suboption header - needs additional argument for it */
3617 if (*(args[cur_arg+1]) == 0) {
3618 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3619 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003622 }
3623 free(curproxy->orgto_hdr_name);
3624 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3625 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3626 cur_arg += 2;
3627 } else {
3628 /* unknown suboption - catchall */
3629 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3630 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003633 }
3634 } /* end while loop */
3635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 else {
3637 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003638 err_code |= ERR_ALERT | ERR_FATAL;
3639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 }
Willy Tarreau93893792009-07-23 13:19:11 +02003641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003643 else if (!strcmp(args[0], "default_backend")) {
3644 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003646
3647 if (*(args[1]) == 0) {
3648 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003651 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003652 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003653 curproxy->defbe.name = strdup(args[1]);
3654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003656 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003657 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003658
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003659 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3660 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 /* enable reconnections to dispatch */
3663 curproxy->options |= PR_O_REDISP;
3664 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003665 else if (!strcmp(args[0], "http-check")) {
3666 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003667 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003668
3669 if (strcmp(args[1], "disable-on-404") == 0) {
3670 /* enable a graceful server shutdown on an HTTP 404 response */
3671 curproxy->options |= PR_O_DISABLE404;
3672 }
Willy Tarreauef781042010-01-27 11:53:01 +01003673 else if (strcmp(args[1], "send-state") == 0) {
3674 /* enable emission of the apparent state of a server in HTTP checks */
3675 curproxy->options2 |= PR_O2_CHK_SNDST;
3676 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003677 else if (strcmp(args[1], "expect") == 0) {
3678 const char *ptr_arg;
3679 int cur_arg;
3680
3681 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3682 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
3685 }
3686
3687 cur_arg = 2;
3688 /* consider exclamation marks, sole or at the beginning of a word */
3689 while (*(ptr_arg = args[cur_arg])) {
3690 while (*ptr_arg == '!') {
3691 curproxy->options2 ^= PR_O2_EXP_INV;
3692 ptr_arg++;
3693 }
3694 if (*ptr_arg)
3695 break;
3696 cur_arg++;
3697 }
3698 /* now ptr_arg points to the beginning of a word past any possible
3699 * exclamation mark, and cur_arg is the argument which holds this word.
3700 */
3701 if (strcmp(ptr_arg, "status") == 0) {
3702 if (!*(args[cur_arg + 1])) {
3703 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3704 file, linenum, args[0], args[1], ptr_arg);
3705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
3707 }
3708 curproxy->options2 |= PR_O2_EXP_STS;
3709 curproxy->expect_str = strdup(args[cur_arg + 1]);
3710 }
3711 else if (strcmp(ptr_arg, "string") == 0) {
3712 if (!*(args[cur_arg + 1])) {
3713 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3714 file, linenum, args[0], args[1], ptr_arg);
3715 err_code |= ERR_ALERT | ERR_FATAL;
3716 goto out;
3717 }
3718 curproxy->options2 |= PR_O2_EXP_STR;
3719 curproxy->expect_str = strdup(args[cur_arg + 1]);
3720 }
3721 else if (strcmp(ptr_arg, "rstatus") == 0) {
3722 if (!*(args[cur_arg + 1])) {
3723 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3724 file, linenum, args[0], args[1], ptr_arg);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
3728 curproxy->options2 |= PR_O2_EXP_RSTS;
3729 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3730 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3731 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3732 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
3735 }
3736 }
3737 else if (strcmp(ptr_arg, "rstring") == 0) {
3738 if (!*(args[cur_arg + 1])) {
3739 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3740 file, linenum, args[0], args[1], ptr_arg);
3741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
3743 }
3744 curproxy->options2 |= PR_O2_EXP_RSTR;
3745 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3746 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3747 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3748 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
3751 }
3752 }
3753 else {
3754 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3755 file, linenum, args[0], args[1], ptr_arg);
3756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
3758 }
3759 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003760 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003761 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003764 }
3765 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003766 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003767 if (curproxy == &defproxy) {
3768 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003771 }
3772
Willy Tarreaub80c2302007-11-30 20:51:32 +01003773 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003775
3776 if (strcmp(args[1], "fail") == 0) {
3777 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003778 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003779 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3780 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003783 }
3784
Willy Tarreauef6494c2010-01-28 17:12:36 +01003785 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003786 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3787 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003790 }
3791 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3792 }
3793 else {
3794 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003797 }
3798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799#ifdef TPROXY
3800 else if (!strcmp(args[0], "transparent")) {
3801 /* enable transparent proxy connections */
3802 curproxy->options |= PR_O_TRANSP;
3803 }
3804#endif
3805 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003806 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003808
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 if (*(args[1]) == 0) {
3810 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 }
3814 curproxy->maxconn = atol(args[1]);
3815 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003816 else if (!strcmp(args[0], "backlog")) { /* backlog */
3817 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003819
3820 if (*(args[1]) == 0) {
3821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003824 }
3825 curproxy->backlog = atol(args[1]);
3826 }
Willy Tarreau86034312006-12-29 00:10:33 +01003827 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003828 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003829 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003830
Willy Tarreau86034312006-12-29 00:10:33 +01003831 if (*(args[1]) == 0) {
3832 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003835 }
3836 curproxy->fullconn = atol(args[1]);
3837 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3839 if (*(args[1]) == 0) {
3840 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003844 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3845 if (err) {
3846 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3847 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003850 }
3851 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
3853 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003854 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 if (curproxy == &defproxy) {
3856 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003860 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003862
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 if (strchr(args[1], ':') == NULL) {
3864 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003868 sk = str2sa(args[1]);
3869 if (!sk) {
3870 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
3873 }
3874 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003875 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
3877 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003878 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003880
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003881 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003882 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3883 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003888 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3889 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3890 err_code |= ERR_WARN;
3891
3892 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3893 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3894 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3895 }
3896 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3897 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3898 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3899 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003900 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3901 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3902 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3903 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003904 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003905 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
3908 }
3909 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003910 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003911 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003912 char *rport, *raddr;
3913 short realport = 0;
3914 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003916 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003920 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003921 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003922 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923
3924 if (!*args[2]) {
3925 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3926 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003929 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003930
3931 err = invalid_char(args[1]);
3932 if (err) {
3933 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3934 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003937 }
3938
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003939 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003940 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003941
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003942 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3943 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3944 err_code |= ERR_ALERT | ERR_ABORT;
3945 goto out;
3946 }
3947
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003948 /* the servers are linked backwards first */
3949 newsrv->next = curproxy->srv;
3950 curproxy->srv = newsrv;
3951 newsrv->proxy = curproxy;
3952 newsrv->conf.file = file;
3953 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003954
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003955 LIST_INIT(&newsrv->pendconns);
3956 do_check = 0;
3957 newsrv->state = SRV_RUNNING; /* early server setup */
3958 newsrv->last_change = now.tv_sec;
3959 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003961 /* several ways to check the port component :
3962 * - IP => port=+0, relative
3963 * - IP: => port=+0, relative
3964 * - IP:N => port=N, absolute
3965 * - IP:+N => port=+N, relative
3966 * - IP:-N => port=-N, relative
3967 */
3968 raddr = strdup(args[2]);
3969 rport = strchr(raddr, ':');
3970 if (rport) {
3971 *rport++ = 0;
3972 realport = atol(rport);
3973 if (!isdigit((unsigned char)*rport))
3974 newsrv->state |= SRV_MAPPORTS;
3975 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003977
Willy Tarreaud5191e72010-02-09 20:50:45 +01003978 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003979 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003980 if (!sk) {
3981 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3982 err_code |= ERR_ALERT | ERR_FATAL;
3983 goto out;
3984 }
3985 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003986
3987 switch (newsrv->addr.ss_family) {
3988 case AF_INET:
3989 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3990 break;
3991 case AF_INET6:
3992 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3993 break;
3994 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003995
3996 newsrv->check_port = curproxy->defsrv.check_port;
3997 newsrv->inter = curproxy->defsrv.inter;
3998 newsrv->fastinter = curproxy->defsrv.fastinter;
3999 newsrv->downinter = curproxy->defsrv.downinter;
4000 newsrv->rise = curproxy->defsrv.rise;
4001 newsrv->fall = curproxy->defsrv.fall;
4002 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4003 newsrv->minconn = curproxy->defsrv.minconn;
4004 newsrv->maxconn = curproxy->defsrv.maxconn;
4005 newsrv->slowstart = curproxy->defsrv.slowstart;
4006 newsrv->onerror = curproxy->defsrv.onerror;
4007 newsrv->consecutive_errors_limit
4008 = curproxy->defsrv.consecutive_errors_limit;
4009 newsrv->uweight = newsrv->iweight
4010 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004012 newsrv->curfd = -1; /* no health-check in progress */
4013 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004014
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004015 cur_arg = 3;
4016 } else {
4017 newsrv = &curproxy->defsrv;
4018 cur_arg = 1;
4019 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004020
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004022 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004023 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004024
4025 if (!*args[cur_arg + 1]) {
4026 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4027 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004030 }
4031
4032 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004033 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004034
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004035 if (newsrv->puid <= 0) {
4036 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004037 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004040 }
4041
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004042 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4043 if (node) {
4044 struct server *target = container_of(node, struct server, conf.id);
4045 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4046 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
4049 }
4050 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004051 cur_arg += 2;
4052 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004053 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 newsrv->cookie = strdup(args[cur_arg + 1]);
4055 newsrv->cklen = strlen(args[cur_arg + 1]);
4056 cur_arg += 2;
4057 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004058 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004059 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4060 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4061 cur_arg += 2;
4062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004064 if (!*args[cur_arg + 1]) {
4065 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4066 file, linenum, args[cur_arg]);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069 }
4070
Willy Tarreaubaaee002006-06-26 02:48:02 +02004071 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004072 if (newsrv->rise <= 0) {
4073 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4074 file, linenum, args[cur_arg]);
4075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
4077 }
4078
Willy Tarreau96839092010-03-29 10:02:24 +02004079 if (newsrv->health)
4080 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081 cur_arg += 2;
4082 }
4083 else if (!strcmp(args[cur_arg], "fall")) {
4084 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004085
4086 if (!*args[cur_arg + 1]) {
4087 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4088 file, linenum, args[cur_arg]);
4089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
4091 }
4092
4093 if (newsrv->fall <= 0) {
4094 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4095 file, linenum, args[cur_arg]);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098 }
4099
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100 cur_arg += 2;
4101 }
4102 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004103 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4104 if (err) {
4105 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4106 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004109 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004110 if (val <= 0) {
4111 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4112 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004115 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004116 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004117 cur_arg += 2;
4118 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004119 else if (!strcmp(args[cur_arg], "fastinter")) {
4120 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4121 if (err) {
4122 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4123 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004126 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004127 if (val <= 0) {
4128 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4129 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004132 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004133 newsrv->fastinter = val;
4134 cur_arg += 2;
4135 }
4136 else if (!strcmp(args[cur_arg], "downinter")) {
4137 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4138 if (err) {
4139 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4140 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004143 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004144 if (val <= 0) {
4145 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4146 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004149 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004150 newsrv->downinter = val;
4151 cur_arg += 2;
4152 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004154 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004155 if (!sk) {
4156 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
4159 }
4160 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004161 cur_arg += 2;
4162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 else if (!strcmp(args[cur_arg], "port")) {
4164 newsrv->check_port = atol(args[cur_arg + 1]);
4165 cur_arg += 2;
4166 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004167 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 newsrv->state |= SRV_BACKUP;
4169 cur_arg ++;
4170 }
4171 else if (!strcmp(args[cur_arg], "weight")) {
4172 int w;
4173 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004174 if (w < 0 || w > 256) {
4175 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004180 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 cur_arg += 2;
4182 }
4183 else if (!strcmp(args[cur_arg], "minconn")) {
4184 newsrv->minconn = atol(args[cur_arg + 1]);
4185 cur_arg += 2;
4186 }
4187 else if (!strcmp(args[cur_arg], "maxconn")) {
4188 newsrv->maxconn = atol(args[cur_arg + 1]);
4189 cur_arg += 2;
4190 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004191 else if (!strcmp(args[cur_arg], "maxqueue")) {
4192 newsrv->maxqueue = atol(args[cur_arg + 1]);
4193 cur_arg += 2;
4194 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004195 else if (!strcmp(args[cur_arg], "slowstart")) {
4196 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004197 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004198 if (err) {
4199 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4200 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004203 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004204 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004205 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4206 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004209 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004210 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004211 cur_arg += 2;
4212 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004213 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004214
4215 if (!*args[cur_arg + 1]) {
4216 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4217 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004220 }
4221
4222 newsrv->trackit = strdup(args[cur_arg + 1]);
4223
4224 cur_arg += 2;
4225 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004226 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 global.maxsock++;
4228 do_check = 1;
4229 cur_arg += 1;
4230 }
Willy Tarreau96839092010-03-29 10:02:24 +02004231 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4232 newsrv->state |= SRV_MAINTAIN;
4233 newsrv->state &= ~SRV_RUNNING;
4234 newsrv->health = 0;
4235 cur_arg += 1;
4236 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004237 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004238 if (!strcmp(args[cur_arg + 1], "none"))
4239 newsrv->observe = HANA_OBS_NONE;
4240 else if (!strcmp(args[cur_arg + 1], "layer4"))
4241 newsrv->observe = HANA_OBS_LAYER4;
4242 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4243 if (curproxy->mode != PR_MODE_HTTP) {
4244 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4245 file, linenum, args[cur_arg + 1]);
4246 err_code |= ERR_ALERT;
4247 }
4248 newsrv->observe = HANA_OBS_LAYER7;
4249 }
4250 else {
4251 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004252 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004253 file, linenum, args[cur_arg], args[cur_arg + 1]);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 }
4257
4258 cur_arg += 2;
4259 }
4260 else if (!strcmp(args[cur_arg], "on-error")) {
4261 if (!strcmp(args[cur_arg + 1], "fastinter"))
4262 newsrv->onerror = HANA_ONERR_FASTINTER;
4263 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4264 newsrv->onerror = HANA_ONERR_FAILCHK;
4265 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4266 newsrv->onerror = HANA_ONERR_SUDDTH;
4267 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4268 newsrv->onerror = HANA_ONERR_MARKDWN;
4269 else {
4270 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004271 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004272 file, linenum, args[cur_arg], args[cur_arg + 1]);
4273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
4275 }
4276
4277 cur_arg += 2;
4278 }
4279 else if (!strcmp(args[cur_arg], "error-limit")) {
4280 if (!*args[cur_arg + 1]) {
4281 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4282 file, linenum, args[cur_arg]);
4283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
4285 }
4286
4287 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4288
4289 if (newsrv->consecutive_errors_limit <= 0) {
4290 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4291 file, linenum, args[cur_arg]);
4292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
4294 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004295 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004296 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004297 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004298 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004299 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004300
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004302#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004303 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004304 file, linenum, "source", "usesrc");
4305#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004306 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004307 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004308#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311 }
4312 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004313 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4314 if (!sk) {
4315 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4316 err_code |= ERR_ALERT | ERR_FATAL;
4317 goto out;
4318 }
4319 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004320
4321 if (port_low != port_high) {
4322 int i;
4323 if (port_low <= 0 || port_low > 65535 ||
4324 port_high <= 0 || port_high > 65535 ||
4325 port_low > port_high) {
4326 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4327 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004330 }
4331 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4332 for (i = 0; i < newsrv->sport_range->size; i++)
4333 newsrv->sport_range->ports[i] = port_low + i;
4334 }
4335
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004337 while (*(args[cur_arg])) {
4338 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004339#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4340#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004341 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4342 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4343 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004346 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004347#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004348 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004349 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004350 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004353 }
4354 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004355 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004356 newsrv->state |= SRV_TPROXY_CLI;
4357 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004358 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004359 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004360 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4361 char *name, *end;
4362
4363 name = args[cur_arg+1] + 7;
4364 while (isspace(*name))
4365 name++;
4366
4367 end = name;
4368 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4369 end++;
4370
4371 newsrv->state &= ~SRV_TPROXY_MASK;
4372 newsrv->state |= SRV_TPROXY_DYN;
4373 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4374 newsrv->bind_hdr_len = end - name;
4375 memcpy(newsrv->bind_hdr_name, name, end - name);
4376 newsrv->bind_hdr_name[end-name] = '\0';
4377 newsrv->bind_hdr_occ = -1;
4378
4379 /* now look for an occurrence number */
4380 while (isspace(*end))
4381 end++;
4382 if (*end == ',') {
4383 end++;
4384 name = end;
4385 if (*end == '-')
4386 end++;
4387 while (isdigit(*end))
4388 end++;
4389 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4390 }
4391
4392 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4393 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4394 " occurrences values smaller than %d.\n",
4395 file, linenum, MAX_HDR_HISTORY);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004399 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004400 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004401 if (!sk) {
4402 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
4405 }
4406 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004407 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004408 }
4409 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004410#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004411 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004412#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004413 cur_arg += 2;
4414 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004415#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004416 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004417 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004420#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4421 } /* "usesrc" */
4422
4423 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4424#ifdef SO_BINDTODEVICE
4425 if (!*args[cur_arg + 1]) {
4426 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4427 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004430 }
4431 if (newsrv->iface_name)
4432 free(newsrv->iface_name);
4433
4434 newsrv->iface_name = strdup(args[cur_arg + 1]);
4435 newsrv->iface_len = strlen(newsrv->iface_name);
4436 global.last_checks |= LSTCHK_NETADM;
4437#else
4438 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4439 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004442#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004443 cur_arg += 2;
4444 continue;
4445 }
4446 /* this keyword in not an option of "source" */
4447 break;
4448 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004450 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004451 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4452 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004455 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004456 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004457 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004458 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 +01004459 file, linenum, newsrv->id);
4460 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004461 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 +01004462 file, linenum);
4463
Willy Tarreau93893792009-07-23 13:19:11 +02004464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004466 }
4467 }
4468
4469 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004470 if (newsrv->trackit) {
4471 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4472 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004473 err_code |= ERR_ALERT | ERR_FATAL;
4474 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004475 }
4476
David du Colombier6f5ccb12011-03-10 22:26:24 +01004477 switch (newsrv->check_addr.ss_family) {
4478 case AF_INET:
4479 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4480 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4481 break;
4482 case AF_INET6:
4483 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4484 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4485 break;
4486 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004487
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4489 newsrv->check_port = realport; /* by default */
4490 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004491 /* not yet valid, because no port was set on
4492 * the server either. We'll check if we have
4493 * a known port on the first listener.
4494 */
4495 struct listener *l;
4496 l = curproxy->listen;
4497 if (l) {
4498 int port;
4499 port = (l->addr.ss_family == AF_INET6)
4500 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4501 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4502 newsrv->check_port = port;
4503 }
4504 }
4505 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4507 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004508 err_code |= ERR_ALERT | ERR_FATAL;
4509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004511
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004512 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004513 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004514 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4515 err_code |= ERR_ALERT | ERR_ABORT;
4516 goto out;
4517 }
4518
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004519 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 newsrv->state |= SRV_CHECKED;
4521 }
4522
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004523 if (!defsrv) {
4524 if (newsrv->state & SRV_BACKUP)
4525 curproxy->srv_bck++;
4526 else
4527 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004528
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004529 newsrv->prev_state = newsrv->state;
4530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 }
4532 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004533 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004534 int facility;
4535
4536 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4537 curproxy->logfac1 = global.logfac1;
4538 curproxy->logsrv1 = global.logsrv1;
4539 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004540 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 curproxy->logfac2 = global.logfac2;
4542 curproxy->logsrv2 = global.logsrv2;
4543 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004544 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004545 }
4546 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004547 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004548
4549 facility = get_log_facility(args[2]);
4550 if (facility < 0) {
4551 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4552 exit(1);
4553 }
4554
4555 level = 7; /* max syslog level = debug */
4556 if (*(args[3])) {
4557 level = get_log_level(args[3]);
4558 if (level < 0) {
4559 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4560 exit(1);
4561 }
4562 }
4563
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004564 minlvl = 0; /* limit syslog level to this level (emerg) */
4565 if (*(args[4])) {
4566 minlvl = get_log_level(args[4]);
4567 if (level < 0) {
4568 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4569 exit(1);
4570 }
4571 }
4572
Robert Tsai81ae1952007-12-05 10:47:29 +01004573 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004574 struct sockaddr_un *sk = str2sun(args[1]);
4575 if (!sk) {
4576 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4577 args[1], (int)sizeof(sk->sun_path) - 1);
4578 err_code |= ERR_ALERT | ERR_FATAL;
4579 goto out;
4580 }
4581 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004582 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004583 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004584 struct sockaddr_storage *sk = str2sa(args[1]);
4585 if (!sk || sk->ss_family != AF_INET) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004586 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
4589 }
David du Colombier6f5ccb12011-03-10 22:26:24 +01004590 logsrv.u.in = *(struct sockaddr_in *)sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004591 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004592 if (!logsrv.u.in.sin_port) {
4593 logsrv.u.in.sin_port =
4594 htons(SYSLOG_PORT);
4595 }
4596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004597
4598 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004599 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 curproxy->logfac1 = facility;
4601 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004602 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 }
4604 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004605 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 curproxy->logfac2 = facility;
4607 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004608 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004609 }
4610 else {
4611 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004614 }
4615 }
4616 else {
4617 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4618 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004619 err_code |= ERR_ALERT | ERR_FATAL;
4620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004621 }
4622 }
4623 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004624 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004625 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004626
Willy Tarreau977b8e42006-12-29 14:19:17 +01004627 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004628 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004629
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004631 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4632 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004636
4637 /* we must first clear any optional default setting */
4638 curproxy->options &= ~PR_O_TPXY_MASK;
4639 free(curproxy->iface_name);
4640 curproxy->iface_name = NULL;
4641 curproxy->iface_len = 0;
4642
Willy Tarreaud5191e72010-02-09 20:50:45 +01004643 sk = str2sa(args[1]);
4644 if (!sk) {
4645 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
4648 }
4649 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004651
4652 cur_arg = 2;
4653 while (*(args[cur_arg])) {
4654 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004655#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4656#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004657 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4658 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4659 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004660 err_code |= ERR_ALERT | ERR_FATAL;
4661 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004662 }
4663#endif
4664 if (!*args[cur_arg + 1]) {
4665 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4666 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004669 }
4670
4671 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004672 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004673 curproxy->options |= PR_O_TPXY_CLI;
4674 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004675 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004676 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004677 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4678 char *name, *end;
4679
4680 name = args[cur_arg+1] + 7;
4681 while (isspace(*name))
4682 name++;
4683
4684 end = name;
4685 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4686 end++;
4687
4688 curproxy->options &= ~PR_O_TPXY_MASK;
4689 curproxy->options |= PR_O_TPXY_DYN;
4690 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4691 curproxy->bind_hdr_len = end - name;
4692 memcpy(curproxy->bind_hdr_name, name, end - name);
4693 curproxy->bind_hdr_name[end-name] = '\0';
4694 curproxy->bind_hdr_occ = -1;
4695
4696 /* now look for an occurrence number */
4697 while (isspace(*end))
4698 end++;
4699 if (*end == ',') {
4700 end++;
4701 name = end;
4702 if (*end == '-')
4703 end++;
4704 while (isdigit(*end))
4705 end++;
4706 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4707 }
4708
4709 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4710 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4711 " occurrences values smaller than %d.\n",
4712 file, linenum, MAX_HDR_HISTORY);
4713 err_code |= ERR_ALERT | ERR_FATAL;
4714 goto out;
4715 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004716 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004717 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004718 if (!sk) {
4719 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4720 err_code |= ERR_ALERT | ERR_FATAL;
4721 goto out;
4722 }
4723 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004724 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004725 }
4726 global.last_checks |= LSTCHK_NETADM;
4727#if !defined(CONFIG_HAP_LINUX_TPROXY)
4728 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004729#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004730#else /* no TPROXY support */
4731 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004732 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004735#endif
4736 cur_arg += 2;
4737 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004738 }
4739
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004740 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4741#ifdef SO_BINDTODEVICE
4742 if (!*args[cur_arg + 1]) {
4743 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4744 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004747 }
4748 if (curproxy->iface_name)
4749 free(curproxy->iface_name);
4750
4751 curproxy->iface_name = strdup(args[cur_arg + 1]);
4752 curproxy->iface_len = strlen(curproxy->iface_name);
4753 global.last_checks |= LSTCHK_NETADM;
4754#else
4755 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4756 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004757 err_code |= ERR_ALERT | ERR_FATAL;
4758 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004759#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004760 cur_arg += 2;
4761 continue;
4762 }
4763 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4764 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004767 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004769 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4770 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4771 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004772 err_code |= ERR_ALERT | ERR_FATAL;
4773 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004776 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4778 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004779 err_code |= ERR_ALERT | ERR_FATAL;
4780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004782
4783 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4784 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004785 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004786 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004788 }
4789 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004790 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4791 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004792 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004793 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004795 }
4796 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004797 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4798 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004799 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004800 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004802 }
4803 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004804 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4805 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004806 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004807 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 }
4810 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004811 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4812 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004813 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004814 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004816 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004817 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004818 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4819 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004820 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004821 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004822 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004823 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004824 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004825 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4826 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004827 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004828 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004829 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004830 }
4831 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004832 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4833 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004834 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004835 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004836 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004837 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004839 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4841 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004844 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004845
4846 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4847 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004848 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004849 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 }
4852 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004853 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4854 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004855 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004856 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858 }
4859 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004860 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4861 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004862 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004863 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 }
4866 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004867 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4868 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004869 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004870 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 }
4873 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004874 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4875 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004876 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004877 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004879 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004880 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004881 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4882 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004883 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004884 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004885 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004888 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004889
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 if (curproxy == &defproxy) {
4891 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004892 err_code |= ERR_ALERT | ERR_FATAL;
4893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004895 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004896 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 if (*(args[1]) == 0) {
4899 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004903
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004904 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4905 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4906 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4907 file, linenum, args[0]);
4908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
4910 }
4911 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4912 }
4913 else if (*args[2]) {
4914 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4915 file, linenum, args[0], args[2]);
4916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918 }
4919
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004920 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004921 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004922 wl->s = strdup(args[1]);
4923 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004924 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 }
4926 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004927 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4929 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004930 err_code |= ERR_ALERT | ERR_FATAL;
4931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004933
Willy Tarreauade5ec42010-01-28 19:33:49 +01004934 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4935 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004936 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 }
4940 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004941 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4942 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004943 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004944 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 }
4947 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004948 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4949 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004950 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004951 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953 }
4954 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004955 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4957 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004958 err_code |= ERR_ALERT | ERR_FATAL;
4959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 }
4961
Willy Tarreauade5ec42010-01-28 19:33:49 +01004962 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4963 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004964 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004965 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
4968 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004969 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4970 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004971 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004972 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
4975 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004976 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4977 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004978 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004979 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
4982 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004983 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004984
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 if (curproxy == &defproxy) {
4986 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004990 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004991 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 if (*(args[1]) == 0) {
4994 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
4998
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004999 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
5000 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
5001 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
5002 file, linenum, args[0]);
5003 err_code |= ERR_ALERT | ERR_FATAL;
5004 goto out;
5005 }
5006 err_code |= warnif_cond_requires_req(cond, file, linenum);
5007 }
5008 else if (*args[2]) {
5009 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5010 file, linenum, args[0], args[2]);
5011 err_code |= ERR_ALERT | ERR_FATAL;
5012 goto out;
5013 }
5014
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005015 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005016 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005017 wl->s = strdup(args[1]);
5018 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
5020 else if (!strcmp(args[0], "errorloc") ||
5021 !strcmp(args[0], "errorloc302") ||
5022 !strcmp(args[0], "errorloc303")) { /* error location */
5023 int errnum, errlen;
5024 char *err;
5025
Willy Tarreau977b8e42006-12-29 14:19:17 +01005026 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005027 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005028
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005030 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 }
5034
5035 errnum = atol(args[1]);
5036 if (!strcmp(args[0], "errorloc303")) {
5037 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5038 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5039 } else {
5040 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5041 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5042 }
5043
Willy Tarreau0f772532006-12-23 20:51:41 +01005044 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5045 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005046 chunk_destroy(&curproxy->errmsg[rc]);
5047 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005048 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005051
5052 if (rc >= HTTP_ERR_SIZE) {
5053 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5054 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 free(err);
5056 }
5057 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005058 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5059 int errnum, errlen, fd;
5060 char *err;
5061 struct stat stat;
5062
5063 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005065
5066 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005067 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005070 }
5071
5072 fd = open(args[2], O_RDONLY);
5073 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5074 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5075 file, linenum, args[2], args[1]);
5076 if (fd >= 0)
5077 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005080 }
5081
Willy Tarreau27a674e2009-08-17 07:23:33 +02005082 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005083 errlen = stat.st_size;
5084 } else {
5085 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005086 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005088 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005089 }
5090
5091 err = malloc(errlen); /* malloc() must succeed during parsing */
5092 errnum = read(fd, err, errlen);
5093 if (errnum != errlen) {
5094 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5095 file, linenum, args[2], args[1]);
5096 close(fd);
5097 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005100 }
5101 close(fd);
5102
5103 errnum = atol(args[1]);
5104 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5105 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005106 chunk_destroy(&curproxy->errmsg[rc]);
5107 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005108 break;
5109 }
5110 }
5111
5112 if (rc >= HTTP_ERR_SIZE) {
5113 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5114 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005116 free(err);
5117 }
5118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005120 struct cfg_kw_list *kwl;
5121 int index;
5122
5123 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5124 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5125 if (kwl->kw[index].section != CFG_LISTEN)
5126 continue;
5127 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5128 /* prepare error message just in case */
5129 snprintf(trash, sizeof(trash),
5130 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005131 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5132 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005133 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005136 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005137 else if (rc > 0) {
5138 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005139 err_code |= ERR_WARN;
5140 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005141 }
Willy Tarreau93893792009-07-23 13:19:11 +02005142 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005143 }
5144 }
5145 }
5146
Willy Tarreau6daf3432008-01-22 16:44:08 +01005147 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005148 err_code |= ERR_ALERT | ERR_FATAL;
5149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 }
Willy Tarreau93893792009-07-23 13:19:11 +02005151 out:
5152 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153}
5154
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005155int
5156cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5157{
5158
5159 int err_code = 0;
5160 const char *err;
5161
5162 if (!strcmp(args[0], "userlist")) { /* new userlist */
5163 struct userlist *newul;
5164
5165 if (!*args[1]) {
5166 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5167 file, linenum, args[0]);
5168 err_code |= ERR_ALERT | ERR_FATAL;
5169 goto out;
5170 }
5171
5172 err = invalid_char(args[1]);
5173 if (err) {
5174 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5175 file, linenum, *err, args[0], args[1]);
5176 err_code |= ERR_ALERT | ERR_FATAL;
5177 goto out;
5178 }
5179
5180 for (newul = userlist; newul; newul = newul->next)
5181 if (!strcmp(newul->name, args[1])) {
5182 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5183 file, linenum, args[1]);
5184 err_code |= ERR_WARN;
5185 goto out;
5186 }
5187
5188 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5189 if (!newul) {
5190 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5191 err_code |= ERR_ALERT | ERR_ABORT;
5192 goto out;
5193 }
5194
5195 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5196 newul->name = strdup(args[1]);
5197
5198 if (!newul->groupusers | !newul->name) {
5199 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5200 err_code |= ERR_ALERT | ERR_ABORT;
5201 goto out;
5202 }
5203
5204 newul->next = userlist;
5205 userlist = newul;
5206
5207 } else if (!strcmp(args[0], "group")) { /* new group */
5208 int cur_arg, i;
5209 const char *err;
5210
5211 if (!*args[1]) {
5212 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5213 file, linenum, args[0]);
5214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
5216 }
5217
5218 err = invalid_char(args[1]);
5219 if (err) {
5220 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5221 file, linenum, *err, args[0], args[1]);
5222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
5224 }
5225
5226 for(i = 0; i < userlist->grpcnt; i++)
5227 if (!strcmp(userlist->groups[i], args[1])) {
5228 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5229 file, linenum, args[1], userlist->name);
5230 err_code |= ERR_ALERT;
5231 goto out;
5232 }
5233
5234 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5235 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5236 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5237 err_code |= ERR_ALERT | ERR_FATAL;
5238 goto out;
5239 }
5240
5241 cur_arg = 2;
5242
5243 while (*args[cur_arg]) {
5244 if (!strcmp(args[cur_arg], "users")) {
5245 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5246 cur_arg += 2;
5247 continue;
5248 } else {
5249 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5250 file, linenum, args[0]);
5251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
5253 }
5254 }
5255
5256 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5257 } else if (!strcmp(args[0], "user")) { /* new user */
5258 struct auth_users *newuser;
5259 int cur_arg;
5260
5261 if (!*args[1]) {
5262 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5263 file, linenum, args[0]);
5264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
5266 }
5267
5268 for (newuser = userlist->users; newuser; newuser = newuser->next)
5269 if (!strcmp(newuser->user, args[1])) {
5270 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5271 file, linenum, args[1], userlist->name);
5272 err_code |= ERR_ALERT;
5273 goto out;
5274 }
5275
5276 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5277 if (!newuser) {
5278 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5279 err_code |= ERR_ALERT | ERR_ABORT;
5280 goto out;
5281 }
5282
5283 newuser->user = strdup(args[1]);
5284
5285 newuser->next = userlist->users;
5286 userlist->users = newuser;
5287
5288 cur_arg = 2;
5289
5290 while (*args[cur_arg]) {
5291 if (!strcmp(args[cur_arg], "password")) {
5292#ifndef CONFIG_HAP_CRYPT
5293 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5294 file, linenum);
5295 err_code |= ERR_ALERT;
5296#endif
5297 newuser->pass = strdup(args[cur_arg + 1]);
5298 cur_arg += 2;
5299 continue;
5300 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5301 newuser->pass = strdup(args[cur_arg + 1]);
5302 newuser->flags |= AU_O_INSECURE;
5303 cur_arg += 2;
5304 continue;
5305 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005306 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005307 cur_arg += 2;
5308 continue;
5309 } else {
5310 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5311 file, linenum, args[0]);
5312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
5315 }
5316 } else {
5317 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5318 err_code |= ERR_ALERT | ERR_FATAL;
5319 }
5320
5321out:
5322 return err_code;
5323}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324
5325/*
5326 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005327 * Returns the error code, 0 if OK, or any combination of :
5328 * - ERR_ABORT: must abort ASAP
5329 * - ERR_FATAL: we can continue parsing but not start the service
5330 * - ERR_WARN: a warning has been emitted
5331 * - ERR_ALERT: an alert has been emitted
5332 * Only the two first ones can stop processing, the two others are just
5333 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005335int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005336{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005337 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005338 FILE *f;
5339 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005341 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 if ((f=fopen(file,"r")) == NULL)
5344 return -1;
5345
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005346 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005347 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005348 char *end;
5349 char *args[MAX_LINE_ARGS + 1];
5350 char *line = thisline;
5351
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 linenum++;
5353
5354 end = line + strlen(line);
5355
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005356 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5357 /* Check if we reached the limit and the last char is not \n.
5358 * Watch out for the last line without the terminating '\n'!
5359 */
5360 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005361 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005362 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005363 }
5364
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005366 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005367 line++;
5368
5369 arg = 0;
5370 args[arg] = line;
5371
5372 while (*line && arg < MAX_LINE_ARGS) {
5373 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5374 * C equivalent value. Other combinations left unchanged (eg: \1).
5375 */
5376 if (*line == '\\') {
5377 int skip = 0;
5378 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5379 *line = line[1];
5380 skip = 1;
5381 }
5382 else if (line[1] == 'r') {
5383 *line = '\r';
5384 skip = 1;
5385 }
5386 else if (line[1] == 'n') {
5387 *line = '\n';
5388 skip = 1;
5389 }
5390 else if (line[1] == 't') {
5391 *line = '\t';
5392 skip = 1;
5393 }
5394 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005395 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396 unsigned char hex1, hex2;
5397 hex1 = toupper(line[2]) - '0';
5398 hex2 = toupper(line[3]) - '0';
5399 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5400 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5401 *line = (hex1<<4) + hex2;
5402 skip = 3;
5403 }
5404 else {
5405 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005406 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005407 }
5408 }
5409 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005410 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005411 end -= skip;
5412 }
5413 line++;
5414 }
5415 else if (*line == '#' || *line == '\n' || *line == '\r') {
5416 /* end of string, end of loop */
5417 *line = 0;
5418 break;
5419 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005420 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005422 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005423 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424 line++;
5425 args[++arg] = line;
5426 }
5427 else {
5428 line++;
5429 }
5430 }
5431
5432 /* empty line */
5433 if (!**args)
5434 continue;
5435
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005436 if (*line) {
5437 /* we had to stop due to too many args.
5438 * Let's terminate the string, print the offending part then cut the
5439 * last arg.
5440 */
5441 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5442 line++;
5443 *line = '\0';
5444
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005445 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005446 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005447 err_code |= ERR_ALERT | ERR_FATAL;
5448 args[arg] = line;
5449 }
5450
Willy Tarreau540abe42007-05-02 20:50:16 +02005451 /* zero out remaining args and ensure that at least one entry
5452 * is zeroed out.
5453 */
5454 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 args[arg] = line;
5456 }
5457
Willy Tarreau3842f002009-06-14 11:39:52 +02005458 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005459 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005460 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005461 for (arg=0; *args[arg+1]; arg++)
5462 args[arg] = args[arg+1]; // shift args after inversion
5463 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005464 else if (!strcmp(args[0], "default")) {
5465 kwm = KWM_DEF;
5466 for (arg=0; *args[arg+1]; arg++)
5467 args[arg] = args[arg+1]; // shift args after inversion
5468 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005469
Willy Tarreau3842f002009-06-14 11:39:52 +02005470 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5471 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005472 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005473 }
5474
Willy Tarreau977b8e42006-12-29 14:19:17 +01005475 if (!strcmp(args[0], "listen") ||
5476 !strcmp(args[0], "frontend") ||
5477 !strcmp(args[0], "backend") ||
5478 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005479 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005481 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005482 cursection = strdup(args[0]);
5483 }
5484 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005486 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005487 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005488 }
5489 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005490 confsect = CFG_USERLIST;
5491 free(cursection);
5492 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005493 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005494 else if (!strcmp(args[0], "peers")) {
5495 confsect = CFG_PEERS;
5496 free(cursection);
5497 cursection = strdup(args[0]);
5498 }
5499
Willy Tarreaubaaee002006-06-26 02:48:02 +02005500 /* else it's a section keyword */
5501
5502 switch (confsect) {
5503 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005504 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005505 break;
5506 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005507 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005508 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005509 case CFG_USERLIST:
5510 err_code |= cfg_parse_users(file, linenum, args, kwm);
5511 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005512 case CFG_PEERS:
5513 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5514 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005515 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005516 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005517 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005518 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005519
5520 if (err_code & ERR_ABORT)
5521 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005523 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005524 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005525 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005526 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005527}
5528
Willy Tarreaubb925012009-07-23 13:36:36 +02005529/*
5530 * Returns the error code, 0 if OK, or any combination of :
5531 * - ERR_ABORT: must abort ASAP
5532 * - ERR_FATAL: we can continue parsing but not start the service
5533 * - ERR_WARN: a warning has been emitted
5534 * - ERR_ALERT: an alert has been emitted
5535 * Only the two first ones can stop processing, the two others are just
5536 * indicators.
5537 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005538int check_config_validity()
5539{
5540 int cfgerr = 0;
5541 struct proxy *curproxy = NULL;
5542 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005543 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005544 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005545 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005546
5547 /*
5548 * Now, check for the integrity of all that we have collected.
5549 */
5550
5551 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005552 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005554 /* first, we will invert the proxy list order */
5555 curproxy = NULL;
5556 while (proxy) {
5557 struct proxy *next;
5558
5559 next = proxy->next;
5560 proxy->next = curproxy;
5561 curproxy = proxy;
5562 if (!next)
5563 break;
5564 proxy = next;
5565 }
5566
Willy Tarreaubaaee002006-06-26 02:48:02 +02005567 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005568 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005569 err_code |= ERR_ALERT | ERR_FATAL;
5570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005571 }
5572
5573 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005574 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005575 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005576 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005577 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005578 unsigned int next_id;
5579
5580 if (!curproxy->uuid) {
5581 /* proxy ID not set, use automatic numbering with first
5582 * spare entry starting with next_pxid.
5583 */
5584 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5585 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5586 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005587 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005588 next_pxid++;
5589
Willy Tarreau55ea7572007-06-17 19:56:27 +02005590
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005592 /* ensure we don't keep listeners uselessly bound */
5593 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 curproxy = curproxy->next;
5595 continue;
5596 }
5597
Willy Tarreauff01a212009-03-15 13:46:16 +01005598 switch (curproxy->mode) {
5599 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005600 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005601 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005602 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5603 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005604 cfgerr++;
5605 }
5606
5607 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005608 Warning("config : servers will be ignored for %s '%s'.\n",
5609 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005610 break;
5611
5612 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005613 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005614 break;
5615
5616 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005617 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005618 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005619 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5620 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005621 cfgerr++;
5622 }
5623 break;
5624 }
5625
5626 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005627 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5628 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005629 cfgerr++;
5630 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005631
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005632 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005633 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005634 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005635 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5636 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005637 cfgerr++;
5638 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005640 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005641 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5642 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005643 cfgerr++;
5644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005646 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005647 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5648 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005649 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005650 }
5651 }
5652 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005653 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005654 /* If no LB algo is set in a backend, and we're not in
5655 * transparent mode, dispatch mode nor proxy mode, we
5656 * want to use balance roundrobin by default.
5657 */
5658 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5659 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 }
5661 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005662
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005663 if (curproxy->options2 & PR_O2_DISPATCH) {
5664 curproxy->options &= ~PR_O_TRANSP;
5665 curproxy->options &= ~PR_O_HTTP_PROXY;
5666 }
5667 else if (curproxy->options & PR_O_HTTP_PROXY) {
5668 curproxy->options2 &= ~PR_O2_DISPATCH;
5669 curproxy->options &= ~PR_O_TRANSP;
5670 }
5671 else if (curproxy->options & PR_O_TRANSP) {
5672 curproxy->options2 &= ~PR_O2_DISPATCH;
5673 curproxy->options &= ~PR_O_HTTP_PROXY;
5674 }
5675
Willy Tarreau82936582007-11-30 15:20:09 +01005676 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5677 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005678 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5679 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005680 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005681 }
5682
Willy Tarreauef781042010-01-27 11:53:01 +01005683 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5684 curproxy->options &= ~PR_O2_CHK_SNDST;
5685 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5686 "send-state", proxy_type_str(curproxy), curproxy->id);
5687 err_code |= ERR_WARN;
5688 }
5689
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005690 /* if a default backend was specified, let's find it */
5691 if (curproxy->defbe.name) {
5692 struct proxy *target;
5693
Alex Williams96532db2009-11-01 21:27:13 -05005694 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005695 if (!target) {
5696 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5697 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005698 cfgerr++;
5699 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005700 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5701 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005702 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005703 } else {
5704 free(curproxy->defbe.name);
5705 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005706 /* we force the backend to be present on at least all of
5707 * the frontend's processes.
5708 */
5709 target->bind_proc = curproxy->bind_proc ?
5710 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 }
5712 }
5713
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005714 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005715 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5716 /* map jump target for ACT_SETBE in req_rep chain */
5717 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005718 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005719 struct proxy *target;
5720
Willy Tarreaua496b602006-12-17 23:15:24 +01005721 if (exp->action != ACT_SETBE)
5722 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005723
Alex Williams96532db2009-11-01 21:27:13 -05005724 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005725 if (!target) {
5726 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5727 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005728 cfgerr++;
5729 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005730 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5731 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005732 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005733 } else {
5734 free((void *)exp->replace);
5735 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005736 /* we force the backend to be present on at least all of
5737 * the frontend's processes.
5738 */
5739 target->bind_proc = curproxy->bind_proc ?
5740 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005741 }
5742 }
5743 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005744
5745 /* find the target proxy for 'use_backend' rules */
5746 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005747 struct proxy *target;
5748
Alex Williams96532db2009-11-01 21:27:13 -05005749 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005750
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005751 if (!target) {
5752 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5753 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005754 cfgerr++;
5755 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005756 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5757 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005758 cfgerr++;
5759 } else {
5760 free((void *)rule->be.name);
5761 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005762 /* we force the backend to be present on at least all of
5763 * the frontend's processes.
5764 */
5765 target->bind_proc = curproxy->bind_proc ?
5766 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005767 }
5768 }
5769
Emeric Brunb982a3d2010-01-04 15:45:53 +01005770 /* find the target table for 'stick' rules */
5771 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5772 struct proxy *target;
5773
Emeric Brun1d33b292010-01-04 15:47:17 +01005774 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5775 if (mrule->flags & STK_IS_STORE)
5776 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5777
Emeric Brunb982a3d2010-01-04 15:45:53 +01005778 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005779 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005780 else
5781 target = curproxy;
5782
5783 if (!target) {
5784 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5785 curproxy->id, mrule->table.name);
5786 cfgerr++;
5787 }
5788 else if (target->table.size == 0) {
5789 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5790 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5791 cfgerr++;
5792 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005793 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005794 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5795 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5796 cfgerr++;
5797 }
5798 else {
5799 free((void *)mrule->table.name);
5800 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005801 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005802 }
5803 }
5804
5805 /* find the target table for 'store response' rules */
5806 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5807 struct proxy *target;
5808
Emeric Brun1d33b292010-01-04 15:47:17 +01005809 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5810
Emeric Brunb982a3d2010-01-04 15:45:53 +01005811 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005812 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005813 else
5814 target = curproxy;
5815
5816 if (!target) {
5817 Alert("Proxy '%s': unable to find store table '%s'.\n",
5818 curproxy->id, mrule->table.name);
5819 cfgerr++;
5820 }
5821 else if (target->table.size == 0) {
5822 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5823 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5824 cfgerr++;
5825 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005826 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005827 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5828 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5829 cfgerr++;
5830 }
5831 else {
5832 free((void *)mrule->table.name);
5833 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005834 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005835 }
5836 }
5837
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005838 /* find the target table for 'tcp-request' layer 4 rules */
5839 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5840 struct proxy *target;
5841
Willy Tarreau56123282010-08-06 19:06:56 +02005842 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005843 continue;
5844
5845 if (trule->act_prm.trk_ctr.table.n)
5846 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5847 else
5848 target = curproxy;
5849
5850 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005851 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5852 curproxy->id, trule->act_prm.trk_ctr.table.n,
5853 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005854 cfgerr++;
5855 }
5856 else if (target->table.size == 0) {
5857 Alert("Proxy '%s': table '%s' used but not configured.\n",
5858 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5859 cfgerr++;
5860 }
5861 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005862 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005863 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5864 cfgerr++;
5865 }
5866 else {
5867 free(trule->act_prm.trk_ctr.table.n);
5868 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005869 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005870 * to pass a list of counters to track and allocate them right here using
5871 * stktable_alloc_data_type().
5872 */
5873 }
5874 }
5875
Willy Tarreaud1f96522010-08-03 19:34:32 +02005876 /* find the target table for 'tcp-request' layer 6 rules */
5877 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5878 struct proxy *target;
5879
Willy Tarreau56123282010-08-06 19:06:56 +02005880 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005881 continue;
5882
5883 if (trule->act_prm.trk_ctr.table.n)
5884 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5885 else
5886 target = curproxy;
5887
5888 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005889 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5890 curproxy->id, trule->act_prm.trk_ctr.table.n,
5891 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005892 cfgerr++;
5893 }
5894 else if (target->table.size == 0) {
5895 Alert("Proxy '%s': table '%s' used but not configured.\n",
5896 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5897 cfgerr++;
5898 }
5899 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005900 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 +02005901 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5902 cfgerr++;
5903 }
5904 else {
5905 free(trule->act_prm.trk_ctr.table.n);
5906 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005907 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005908 * to pass a list of counters to track and allocate them right here using
5909 * stktable_alloc_data_type().
5910 */
5911 }
5912 }
5913
Emeric Brun32da3c42010-09-23 18:39:19 +02005914 if (curproxy->table.peers.name) {
5915 struct peers *curpeers = peers;
5916
5917 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5918 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5919 free((void *)curproxy->table.peers.name);
5920 curproxy->table.peers.p = peers;
5921 break;
5922 }
5923 }
5924
5925 if (!curpeers) {
5926 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5927 curproxy->id, curproxy->table.peers.name);
5928 cfgerr++;
5929 }
5930 else if (!curpeers->peers_fe) {
5931 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5932 curproxy->id, curpeers->id);
5933 cfgerr++;
5934 }
5935 }
5936
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005937 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5938 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005939 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5940 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5941 "proxy", curproxy->id);
5942 cfgerr++;
5943 goto out_uri_auth_compat;
5944 }
5945
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005946 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005947 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005948 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005949 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005950
Willy Tarreau95fa4692010-02-01 13:05:50 +01005951 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5952 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005953
5954 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005955 uri_auth_compat_req[i++] = "realm";
5956 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5957 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005958
Willy Tarreau95fa4692010-02-01 13:05:50 +01005959 uri_auth_compat_req[i++] = "unless";
5960 uri_auth_compat_req[i++] = "{";
5961 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5962 uri_auth_compat_req[i++] = "}";
5963 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005964
Willy Tarreau95fa4692010-02-01 13:05:50 +01005965 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5966 if (!req_acl) {
5967 cfgerr++;
5968 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005969 }
5970
Willy Tarreau95fa4692010-02-01 13:05:50 +01005971 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5972
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005973 if (curproxy->uri_auth->auth_realm) {
5974 free(curproxy->uri_auth->auth_realm);
5975 curproxy->uri_auth->auth_realm = NULL;
5976 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005977
5978 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005979 }
5980out_uri_auth_compat:
5981
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005982 cfgerr += acl_find_targets(curproxy);
5983
Willy Tarreau2738a142006-07-08 17:28:09 +02005984 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005985 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005986 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005987 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005988 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005989 " | While not properly invalid, you will certainly encounter various problems\n"
5990 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005991 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005992 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005993 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005994 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005995
Willy Tarreau1fa31262007-12-03 00:36:16 +01005996 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5997 * We must still support older configurations, so let's find out whether those
5998 * parameters have been set or must be copied from contimeouts.
5999 */
6000 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006001 if (!curproxy->timeout.tarpit ||
6002 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006003 /* tarpit timeout not set. We search in the following order:
6004 * default.tarpit, curr.connect, default.connect.
6005 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006006 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006007 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006008 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006009 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006010 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006011 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006012 }
6013 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006014 (!curproxy->timeout.queue ||
6015 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006016 /* queue timeout not set. We search in the following order:
6017 * default.queue, curr.connect, default.connect.
6018 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006019 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006020 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006021 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006022 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006023 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006024 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006025 }
6026 }
6027
Willy Tarreau07a54902010-03-29 18:33:29 +02006028 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006029 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6030 curproxy->check_req = (char *)malloc(curproxy->check_len);
6031 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006032 }
6033
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006034 /* The small pools required for the capture lists */
6035 if (curproxy->nb_req_cap)
6036 curproxy->req_cap_pool = create_pool("ptrcap",
6037 curproxy->nb_req_cap * sizeof(char *),
6038 MEM_F_SHARED);
6039 if (curproxy->nb_rsp_cap)
6040 curproxy->rsp_cap_pool = create_pool("ptrcap",
6041 curproxy->nb_rsp_cap * sizeof(char *),
6042 MEM_F_SHARED);
6043
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006044 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6045 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6046 MEM_F_SHARED);
6047
Willy Tarreau86034312006-12-29 00:10:33 +01006048 /* for backwards compatibility with "listen" instances, if
6049 * fullconn is not set but maxconn is set, then maxconn
6050 * is used.
6051 */
6052 if (!curproxy->fullconn)
6053 curproxy->fullconn = curproxy->maxconn;
6054
Willy Tarreaubaaee002006-06-26 02:48:02 +02006055 /* first, we will invert the servers list order */
6056 newsrv = NULL;
6057 while (curproxy->srv) {
6058 struct server *next;
6059
6060 next = curproxy->srv->next;
6061 curproxy->srv->next = newsrv;
6062 newsrv = curproxy->srv;
6063 if (!next)
6064 break;
6065 curproxy->srv = next;
6066 }
6067
Willy Tarreaudd701652010-05-25 23:03:02 +02006068 /* assign automatic UIDs to servers which don't have one yet */
6069 next_id = 1;
6070 newsrv = curproxy->srv;
6071 while (newsrv != NULL) {
6072 if (!newsrv->puid) {
6073 /* server ID not set, use automatic numbering with first
6074 * spare entry starting with next_svid.
6075 */
6076 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6077 newsrv->conf.id.key = newsrv->puid = next_id;
6078 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6079 }
6080 next_id++;
6081 newsrv = newsrv->next;
6082 }
6083
Willy Tarreau20697042007-11-15 23:26:18 +01006084 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006085 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006086
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006087 /* We have to initialize the server lookup mechanism depending
6088 * on what LB algorithm was choosen.
6089 */
6090
6091 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6092 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6093 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006094 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6095 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6096 init_server_map(curproxy);
6097 } else {
6098 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6099 fwrr_init_server_groups(curproxy);
6100 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006101 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006102
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006103 case BE_LB_KIND_LC:
6104 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006105 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006106 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006107
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006108 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006109 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6110 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6111 chash_init_server_tree(curproxy);
6112 } else {
6113 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6114 init_server_map(curproxy);
6115 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006116 break;
6117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006118
6119 if (curproxy->options & PR_O_LOGASAP)
6120 curproxy->to_log &= ~LW_BYTES;
6121
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006122 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6123 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6124 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6125 proxy_type_str(curproxy), curproxy->id);
6126 err_code |= ERR_WARN;
6127 }
6128
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006129 if (curproxy->mode != PR_MODE_HTTP) {
6130 int optnum;
6131
6132 if (curproxy->options & PR_O_COOK_ANY) {
6133 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6134 proxy_type_str(curproxy), curproxy->id);
6135 err_code |= ERR_WARN;
6136 }
6137
6138 if (curproxy->uri_auth) {
6139 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6140 proxy_type_str(curproxy), curproxy->id);
6141 err_code |= ERR_WARN;
6142 curproxy->uri_auth = NULL;
6143 }
6144
6145 if (curproxy->options & PR_O_FWDFOR) {
6146 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6147 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6148 err_code |= ERR_WARN;
6149 curproxy->options &= ~PR_O_FWDFOR;
6150 }
6151
6152 if (curproxy->options & PR_O_ORGTO) {
6153 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6154 "originalto", proxy_type_str(curproxy), curproxy->id);
6155 err_code |= ERR_WARN;
6156 curproxy->options &= ~PR_O_ORGTO;
6157 }
6158
6159 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6160 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6161 (curproxy->cap & cfg_opts[optnum].cap) &&
6162 (curproxy->options & cfg_opts[optnum].val)) {
6163 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6164 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6165 err_code |= ERR_WARN;
6166 curproxy->options &= ~cfg_opts[optnum].val;
6167 }
6168 }
6169
6170 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6171 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6172 (curproxy->cap & cfg_opts2[optnum].cap) &&
6173 (curproxy->options2 & cfg_opts2[optnum].val)) {
6174 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6175 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6176 err_code |= ERR_WARN;
6177 curproxy->options2 &= ~cfg_opts2[optnum].val;
6178 }
6179 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006180
Willy Tarreauefa5f512010-03-30 20:13:29 +02006181#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006182 if (curproxy->bind_hdr_occ) {
6183 curproxy->bind_hdr_occ = 0;
6184 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6185 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6186 err_code |= ERR_WARN;
6187 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006188#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006189 }
6190
Willy Tarreaubaaee002006-06-26 02:48:02 +02006191 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006192 * ensure that we're not cross-dressing a TCP server into HTTP.
6193 */
6194 newsrv = curproxy->srv;
6195 while (newsrv != NULL) {
6196 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006197 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6198 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006199 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006200 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006201
Willy Tarreauefa5f512010-03-30 20:13:29 +02006202#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006203 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6204 newsrv->bind_hdr_occ = 0;
6205 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6206 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6207 err_code |= ERR_WARN;
6208 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006209#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006210 newsrv = newsrv->next;
6211 }
6212
6213 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006214 * If this server supports a maxconn parameter, it needs a dedicated
6215 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006216 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006217 */
6218 newsrv = curproxy->srv;
6219 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006220 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006221 /* Only 'minconn' was specified, or it was higher than or equal
6222 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6223 * this will avoid further useless expensive computations.
6224 */
6225 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006226 } else if (newsrv->maxconn && !newsrv->minconn) {
6227 /* minconn was not specified, so we set it to maxconn */
6228 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006229 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006230 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6231 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006232 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006233 }
6234
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006235 if (newsrv->trackit) {
6236 struct proxy *px;
6237 struct server *srv;
6238 char *pname, *sname;
6239
6240 pname = newsrv->trackit;
6241 sname = strrchr(pname, '/');
6242
6243 if (sname)
6244 *sname++ = '\0';
6245 else {
6246 sname = pname;
6247 pname = NULL;
6248 }
6249
6250 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006251 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006252 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006253 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6254 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006255 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006256 cfgerr++;
6257 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006258 }
6259 } else
6260 px = curproxy;
6261
6262 srv = findserver(px, sname);
6263 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006264 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6265 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006266 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006267 cfgerr++;
6268 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006269 }
6270
6271 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006272 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006273 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006274 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006275 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006276 cfgerr++;
6277 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006278 }
6279
6280 if (curproxy != px &&
6281 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006282 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006283 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006284 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006285 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006286 cfgerr++;
6287 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006288 }
6289
6290 newsrv->tracked = srv;
6291 newsrv->tracknext = srv->tracknext;
6292 srv->tracknext = newsrv;
6293
6294 free(newsrv->trackit);
6295 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006296 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006297 newsrv = newsrv->next;
6298 }
6299
Willy Tarreauc1a21672009-08-16 22:37:44 +02006300 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006301 curproxy->accept = frontend_accept;
6302
Willy Tarreauc1a21672009-08-16 22:37:44 +02006303 if (curproxy->tcp_req.inspect_delay ||
6304 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006305 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006306
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006307 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006308 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006309 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006310 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006311
6312 /* both TCP and HTTP must check switching rules */
6313 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6314 }
6315
6316 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006317 if (curproxy->tcp_req.inspect_delay ||
6318 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6319 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6320
Emeric Brun97679e72010-09-23 17:56:44 +02006321 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6322 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6323
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006324 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006325 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006326 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006327 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006328
6329 /* If the backend does requires RDP cookie persistence, we have to
6330 * enable the corresponding analyser.
6331 */
6332 if (curproxy->options2 & PR_O2_RDPC_PRST)
6333 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6334 }
6335
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006336 listener = NULL;
6337 while (curproxy->listen) {
6338 struct listener *next;
6339
6340 next = curproxy->listen->next;
6341 curproxy->listen->next = listener;
6342 listener = curproxy->listen;
6343
6344 if (!next)
6345 break;
6346
6347 curproxy->listen = next;
6348 }
6349
Willy Tarreaue6b98942007-10-29 01:09:36 +01006350 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006351 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006352 listener = curproxy->listen;
6353 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006354 if (!listener->luid) {
6355 /* listener ID not set, use automatic numbering with first
6356 * spare entry starting with next_luid.
6357 */
6358 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6359 listener->conf.id.key = listener->luid = next_id;
6360 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006361 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006362 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006363
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006364 /* enable separate counters */
6365 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6366 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6367 if (!listener->name) {
6368 sprintf(trash, "sock-%d", listener->luid);
6369 listener->name = strdup(trash);
6370 }
6371 }
6372
Willy Tarreaue6b98942007-10-29 01:09:36 +01006373 if (curproxy->options & PR_O_TCP_NOLING)
6374 listener->options |= LI_O_NOLINGER;
6375 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006376 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006377 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006378 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006379 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006380 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006381 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006382
Willy Tarreau8a956912010-10-15 14:27:08 +02006383 if (listener->options & LI_O_ACC_PROXY)
6384 listener->analysers |= AN_REQ_DECODE_PROXY;
6385
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006386 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6387 listener->options |= LI_O_TCP_RULES;
6388
Willy Tarreaude3041d2010-05-31 10:56:17 +02006389 if (curproxy->mon_mask.s_addr)
6390 listener->options |= LI_O_CHK_MONNET;
6391
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006392 /* smart accept mode is automatic in HTTP mode */
6393 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6394 (curproxy->mode == PR_MODE_HTTP &&
6395 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6396 listener->options |= LI_O_NOQUICKACK;
6397
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006398 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006399 listener = listener->next;
6400 }
6401
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006402 /* Check multi-process mode compatibility for the current proxy */
6403 if (global.nbproc > 1) {
6404 int nbproc = 0;
6405 if (curproxy->bind_proc) {
6406 int proc;
6407 for (proc = 0; proc < global.nbproc; proc++) {
6408 if (curproxy->bind_proc & (1 << proc)) {
6409 nbproc++;
6410 }
6411 }
6412 } else {
6413 nbproc = global.nbproc;
6414 }
6415 if (curproxy->table.peers.name) {
6416 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6417 curproxy->id);
6418 cfgerr++;
6419 }
6420 if (nbproc > 1) {
6421 if (curproxy->uri_auth) {
6422 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6423 curproxy->id);
6424 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6425 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6426 curproxy->id);
6427 }
6428 }
6429 if (curproxy->appsession_name) {
6430 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6431 curproxy->id);
6432 }
6433 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6434 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6435 curproxy->id);
6436 }
6437 }
6438 }
6439
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 curproxy = curproxy->next;
6441 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006442
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006443 /* Check multi-process mode compatibility */
6444 if (global.nbproc > 1) {
6445 if (global.stats_fe) {
6446 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6447 }
6448 }
6449
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006450 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6451 struct auth_users *curuser;
6452 int g;
6453
6454 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6455 unsigned int group_mask = 0;
6456 char *group = NULL;
6457
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006458 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006459 continue;
6460
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006461 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006462
6463 for (g = 0; g < curuserlist->grpcnt; g++)
6464 if (!strcmp(curuserlist->groups[g], group))
6465 break;
6466
6467 if (g == curuserlist->grpcnt) {
6468 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6469 curuserlist->name, group, curuser->user);
6470 err_code |= ERR_ALERT | ERR_FATAL;
6471 goto out;
6472 }
6473
6474 group_mask |= (1 << g);
6475 }
6476
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006477 free(curuser->u.groups);
6478 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006479 }
6480
6481 for (g = 0; g < curuserlist->grpcnt; g++) {
6482 char *user = NULL;
6483
6484 if (!curuserlist->groupusers[g])
6485 continue;
6486
6487 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6488 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6489 if (!strcmp(curuser->user, user))
6490 break;
6491
6492 if (!curuser) {
6493 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6494 curuserlist->name, user, curuserlist->groups[g]);
6495 err_code |= ERR_ALERT | ERR_FATAL;
6496 goto out;
6497 }
6498
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006499 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006500 }
6501
6502 free(curuserlist->groupusers[g]);
6503 }
6504
6505 free(curuserlist->groupusers);
6506
6507#ifdef DEBUG_AUTH
6508 for (g = 0; g < curuserlist->grpcnt; g++) {
6509 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6510
6511 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6512 if (curuser->group_mask & (1 << g))
6513 fprintf(stderr, " %s", curuser->user);
6514 }
6515
6516 fprintf(stderr, "\n");
6517 }
6518#endif
6519
6520 }
6521
Willy Tarreau056f5682010-06-06 15:51:11 +02006522 /* initialize stick-tables on backend capable proxies. This must not
6523 * be done earlier because the data size may be discovered while parsing
6524 * other proxies.
6525 */
6526 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006527 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006528
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006529 /*
6530 * Recount currently required checks.
6531 */
6532
6533 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6534 int optnum;
6535
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006536 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6537 if (curproxy->options & cfg_opts[optnum].val)
6538 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006539
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006540 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6541 if (curproxy->options2 & cfg_opts2[optnum].val)
6542 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006543 }
6544
Willy Tarreaubb925012009-07-23 13:36:36 +02006545 if (cfgerr > 0)
6546 err_code |= ERR_ALERT | ERR_FATAL;
6547 out:
6548 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549}
6550
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006551/*
6552 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6553 * parsing sessions.
6554 */
6555void cfg_register_keywords(struct cfg_kw_list *kwl)
6556{
6557 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6558}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006559
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006560/*
6561 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6562 */
6563void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6564{
6565 LIST_DEL(&kwl->list);
6566 LIST_INIT(&kwl->list);
6567}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568
6569/*
6570 * Local variables:
6571 * c-indent-level: 8
6572 * c-basic-offset: 8
6573 * End:
6574 */