blob: 28eb1cab7f8c6a622d400b6f3338dbe057d75b1d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010047#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010053#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010062#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010064#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065
66
Willy Tarreauf3c69202006-07-09 16:42:34 +020067/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
68 * ssl-hello-chk option to ensure that the remote server speaks SSL.
69 *
70 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
71 */
72const char sslv3_client_hello_pkt[] = {
73 "\x16" /* ContentType : 0x16 = Hanshake */
74 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
75 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
76 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
77 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
78 "\x03\x00" /* Hello Version : 0x0300 = v3 */
79 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
80 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
81 "\x00" /* Session ID length : empty (no session ID) */
82 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
83 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
84 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
85 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
86 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
87 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
88 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
89 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
90 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
91 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
92 "\x00\x38" "\x00\x39" "\x00\x3A"
93 "\x01" /* Compression Length : 0x01 = 1 byte for types */
94 "\x00" /* Compression Type : 0x00 = NULL compression */
95};
96
Willy Tarreau3842f002009-06-14 11:39:52 +020097/* various keyword modifiers */
98enum kw_mod {
99 KWM_STD = 0, /* normal */
100 KWM_NO, /* "no" prefixed before the keyword */
101 KWM_DEF, /* "default" prefixed before the keyword */
102};
103
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106 const char *name;
107 unsigned int val;
108 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100110 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111};
112
113/* proxy->options */
114static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
117 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
118 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
119 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
120 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
121 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
122 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
126 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
128 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
129 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
130 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
131 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100132#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100134#else
135 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100136#endif
137
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139};
140
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100141/* proxy->options2 */
142static const struct cfg_opt cfg_opts2[] =
143{
144#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100148#else
149 { "splice-request", 0, 0, 0, 0 },
150 { "splice-response", 0, 0, 0, 0 },
151 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
154 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
155 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
156 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
157 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
158 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
161 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
162 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200163 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200186static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
189 char *c, *next, *range, *dupstr;
190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
210 Alert("Socket path '%s' too long (max %d)\n", str, max_path_len);
211 goto fail;
212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200215 ss.ss_family = AF_UNIX;
216 if (global.unix_bind.prefix) {
217 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
218 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 }
Emeric Bruned760922010-10-22 17:59:25 +0200220 else {
221 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
222 }
223 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 }
225 else {
Emeric Bruned760922010-10-22 17:59:25 +0200226 /* 2) look for the addr/port delimiter, it's the last colon. */
227 if ((range = strrchr(str, ':')) == NULL) {
228 Alert("Missing port number: '%s'\n", str);
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 }
Emeric Bruned760922010-10-22 17:59:25 +0200231
232 *range++ = 0;
233
234 if (strrchr(str, ':') != NULL) {
235 /* IPv6 address contains ':' */
236 memset(&ss, 0, sizeof(ss));
237 ss.ss_family = AF_INET6;
238
239 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
240 Alert("Invalid server address: '%s'\n", str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Emeric Bruned760922010-10-22 17:59:25 +0200244 else {
245 memset(&ss, 0, sizeof(ss));
246 ss.ss_family = AF_INET;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Emeric Bruned760922010-10-22 17:59:25 +0200248 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
249 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
250 }
251 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
252 struct hostent *he;
253
254 if ((he = gethostbyname(str)) == NULL) {
255 Alert("Invalid server name: '%s'\n", str);
256 goto fail;
257 }
258 else
259 ((struct sockaddr_in *)&ss)->sin_addr =
260 *(struct in_addr *) *(he->h_addr_list);
261 }
262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
Emeric Bruned760922010-10-22 17:59:25 +0200264 /* 3) look for the port-end delimiter */
265 if ((c = strchr(range, '-')) != NULL) {
266 *c++ = 0;
267 end = atol(c);
268 }
269 else {
270 end = atol(range);
271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272
Emeric Bruned760922010-10-22 17:59:25 +0200273 port = atol(range);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
Emeric Bruned760922010-10-22 17:59:25 +0200275 if (port < 1 || port > 65535) {
276 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
277 goto fail;
278 }
279
280 if (end < 1 || end > 65535) {
281 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
282 goto fail;
283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 }
285
286 for (; port <= end; port++) {
287 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200288 l->next = curproxy->listen;
289 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290
291 l->fd = -1;
292 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 l->state = LI_INIT;
294
Emeric Bruned760922010-10-22 17:59:25 +0200295 if(ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100297 tcpv4_add_listener(l);
298 }
Emeric Bruned760922010-10-22 17:59:25 +0200299 else if (ss.ss_family == AF_INET6) {
300 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
301 tcpv6_add_listener(l);
302 }
303 else {
304 l->perm.ux.gid = l->perm.ux.uid = -1;
305 l->perm.ux.mode = 0;
306 uxst_add_listener(l);
307 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200308
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200309 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100310 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311 } /* end for(port) */
312 } /* end while(next) */
313 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 fail:
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318}
319
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320/*
321 * Sends a warning if proxy <proxy> does not have at least one of the
322 * capabilities in <cap>. An optionnal <hint> may be added at the end
323 * of the warning to help the user. Returns 1 if a warning was emitted
324 * or 0 if the condition is valid.
325 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100326int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100327{
328 char *msg;
329
330 switch (cap) {
331 case PR_CAP_BE: msg = "no backend"; break;
332 case PR_CAP_FE: msg = "no frontend"; break;
333 case PR_CAP_RS: msg = "no ruleset"; break;
334 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
335 default: msg = "not enough"; break;
336 }
337
338 if (!(proxy->cap & cap)) {
339 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100340 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100341 return 1;
342 }
343 return 0;
344}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200345
Willy Tarreau61d18892009-03-31 10:49:21 +0200346/* Report a warning if a rule is placed after a 'block' rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
351 if (!LIST_ISEMPTY(&proxy->block_cond)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a reqrewrite rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (proxy->req_exp) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a reqadd rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100377 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* Report a warning if a rule is placed after a redirect rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
398/* Report a warning if a rule is placed after a 'use_backend' rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
411/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
415 warnif_rule_after_reqadd(proxy, file, line, arg) ||
416 warnif_rule_after_redirect(proxy, file, line, arg) ||
417 warnif_rule_after_use_backend(proxy, file, line, arg);
418}
419
420/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100421int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200422{
423 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
424 warnif_rule_after_redirect(proxy, file, line, arg) ||
425 warnif_rule_after_use_backend(proxy, file, line, arg);
426}
427
428/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
431 return warnif_rule_after_redirect(proxy, file, line, arg) ||
432 warnif_rule_after_use_backend(proxy, file, line, arg);
433}
434
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100435/* Report it if a request ACL condition uses some response-only parameters. It
436 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
447 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100452/* Report it if a request ACL condition uses some request-only volatile parameters.
453 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
454 * Note that <cond> may be NULL and then will be ignored.
455 */
456static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
457{
458 struct acl *acl;
459
460 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
461 return 0;
462
463 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
464 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
465 file, line, acl ? acl->name : "(unknown)");
466 return ERR_WARN;
467}
468
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100469
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200471 * parse a line in a <global> section. Returns the error code, 0 if OK, or
472 * any combination of :
473 * - ERR_ABORT: must abort ASAP
474 * - ERR_FATAL: we can continue parsing but not start the service
475 * - ERR_WARN: a warning has been emitted
476 * - ERR_ALERT: an alert has been emitted
477 * Only the two first ones can stop processing, the two others are just
478 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200480int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481{
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483
484 if (!strcmp(args[0], "global")) { /* new section */
485 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487 }
488 else if (!strcmp(args[0], "daemon")) {
489 global.mode |= MODE_DAEMON;
490 }
491 else if (!strcmp(args[0], "debug")) {
492 global.mode |= MODE_DEBUG;
493 }
494 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100495 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200496 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200497 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100498 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200499 }
500 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100501 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100504 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100506 else if (!strcmp(args[0], "nosplice")) {
507 global.tune.options &= ~GTUNE_USE_SPLICE;
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "quiet")) {
510 global.mode |= MODE_QUIET;
511 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200512 else if (!strcmp(args[0], "tune.maxpollevents")) {
513 if (global.tune.maxpollevents != 0) {
514 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200515 err_code |= ERR_ALERT;
516 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200517 }
518 if (*(args[1]) == 0) {
519 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200520 err_code |= ERR_ALERT | ERR_FATAL;
521 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200522 }
523 global.tune.maxpollevents = atol(args[1]);
524 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100525 else if (!strcmp(args[0], "tune.maxaccept")) {
526 if (global.tune.maxaccept != 0) {
527 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200528 err_code |= ERR_ALERT;
529 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100530 }
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100535 }
536 global.tune.maxaccept = atol(args[1]);
537 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200538 else if (!strcmp(args[0], "tune.chksize")) {
539 if (*(args[1]) == 0) {
540 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT | ERR_FATAL;
542 goto out;
543 }
544 global.tune.chksize = atol(args[1]);
545 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200546 else if (!strcmp(args[0], "tune.bufsize")) {
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.bufsize = atol(args[1]);
553 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
554 global.tune.maxrewrite = global.tune.bufsize / 2;
555 }
556 else if (!strcmp(args[0], "tune.maxrewrite")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.maxrewrite = atol(args[1]);
563 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
564 global.tune.maxrewrite = global.tune.bufsize / 2;
565 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100566 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
567 if (global.tune.client_rcvbuf != 0) {
568 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT;
570 goto out;
571 }
572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
576 }
577 global.tune.client_rcvbuf = atol(args[1]);
578 }
579 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
580 if (global.tune.server_rcvbuf != 0) {
581 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT;
583 goto out;
584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.server_rcvbuf = atol(args[1]);
591 }
592 else if (!strcmp(args[0], "tune.sndbuf.client")) {
593 if (global.tune.client_sndbuf != 0) {
594 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT;
596 goto out;
597 }
598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 global.tune.client_sndbuf = atol(args[1]);
604 }
605 else if (!strcmp(args[0], "tune.sndbuf.server")) {
606 if (global.tune.server_sndbuf != 0) {
607 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT;
609 goto out;
610 }
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.server_sndbuf = atol(args[1]);
617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 else if (!strcmp(args[0], "uid")) {
619 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624 if (*(args[1]) == 0) {
625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 }
629 global.uid = atol(args[1]);
630 }
631 else if (!strcmp(args[0], "gid")) {
632 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 }
642 global.gid = atol(args[1]);
643 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 /* user/group name handling */
645 else if (!strcmp(args[0], "user")) {
646 struct passwd *ha_user;
647 if (global.uid != 0) {
648 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200649 err_code |= ERR_ALERT;
650 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200651 }
652 errno = 0;
653 ha_user = getpwnam(args[1]);
654 if (ha_user != NULL) {
655 global.uid = (int)ha_user->pw_uid;
656 }
657 else {
658 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200660 }
661 }
662 else if (!strcmp(args[0], "group")) {
663 struct group *ha_group;
664 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200665 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200666 err_code |= ERR_ALERT;
667 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 errno = 0;
670 ha_group = getgrnam(args[1]);
671 if (ha_group != NULL) {
672 global.gid = (int)ha_group->gr_gid;
673 }
674 else {
675 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200677 }
678 }
679 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 else if (!strcmp(args[0], "nbproc")) {
681 if (global.nbproc != 0) {
682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 }
691 global.nbproc = atol(args[1]);
692 }
693 else if (!strcmp(args[0], "maxconn")) {
694 if (global.maxconn != 0) {
695 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 global.maxconn = atol(args[1]);
705#ifdef SYSTEM_MAXCONN
706 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
707 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
708 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 }
711#endif /* SYSTEM_MAXCONN */
712 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100713 else if (!strcmp(args[0], "maxpipes")) {
714 if (global.maxpipes != 0) {
715 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200716 err_code |= ERR_ALERT;
717 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100718 }
719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100723 }
724 global.maxpipes = atol(args[1]);
725 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 else if (!strcmp(args[0], "ulimit-n")) {
727 if (global.rlimit_nofile != 0) {
728 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT;
730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 }
732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 }
737 global.rlimit_nofile = atol(args[1]);
738 }
739 else if (!strcmp(args[0], "chroot")) {
740 if (global.chroot != NULL) {
741 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200742 err_code |= ERR_ALERT;
743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 }
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 global.chroot = strdup(args[1]);
751 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200752 else if (!strcmp(args[0], "description")) {
753 int i, len=0;
754 char *d;
755
756 if (!*args[1]) {
757 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
758 file, linenum, args[0]);
759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
761 }
762
763 for(i=1; *args[i]; i++)
764 len += strlen(args[i])+1;
765
766 if (global.desc)
767 free(global.desc);
768
769 global.desc = d = (char *)calloc(1, len);
770
771 d += sprintf(d, "%s", args[1]);
772 for(i=2; *args[i]; i++)
773 d += sprintf(d, " %s", args[i]);
774 }
775 else if (!strcmp(args[0], "node")) {
776 int i;
777 char c;
778
779 for (i=0; args[1][i]; i++) {
780 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100781 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
782 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200783 break;
784 }
785
786 if (!i || args[1][i]) {
787 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
788 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
789 file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
793
794 if (global.node)
795 free(global.node);
796
797 global.node = strdup(args[1]);
798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 else if (!strcmp(args[0], "pidfile")) {
800 if (global.pidfile != NULL) {
801 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200802 err_code |= ERR_ALERT;
803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 }
810 global.pidfile = strdup(args[1]);
811 }
Emeric Bruned760922010-10-22 17:59:25 +0200812 else if (!strcmp(args[0], "unix-bind")) {
813 int cur_arg = 1;
814 while (*(args[cur_arg])) {
815 if (!strcmp(args[cur_arg], "prefix")) {
816 if (global.unix_bind.prefix != NULL) {
817 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
818 err_code |= ERR_ALERT;
819 cur_arg += 2;
820 continue;
821 }
822
823 if (*(args[cur_arg+1]) == 0) {
824 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.unix_bind.prefix = strdup(args[cur_arg+1]);
829 cur_arg += 2;
830 continue;
831 }
832
833 if (!strcmp(args[cur_arg], "mode")) {
834
835 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
836 cur_arg += 2;
837 continue;
838 }
839
840 if (!strcmp(args[cur_arg], "uid")) {
841
842 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
843 cur_arg += 2;
844 continue;
845 }
846
847 if (!strcmp(args[cur_arg], "gid")) {
848
849 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
850 cur_arg += 2;
851 continue;
852 }
853
854 if (!strcmp(args[cur_arg], "user")) {
855 struct passwd *user;
856
857 user = getpwnam(args[cur_arg + 1]);
858 if (!user) {
859 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
860 file, linenum, args[0], args[cur_arg + 1 ]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864
865 global.unix_bind.ux.uid = user->pw_uid;
866 cur_arg += 2;
867 continue;
868 }
869
870 if (!strcmp(args[cur_arg], "group")) {
871 struct group *group;
872
873 group = getgrnam(args[cur_arg + 1]);
874 if (!group) {
875 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
876 file, linenum, args[0], args[cur_arg + 1 ]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880
881 global.unix_bind.ux.gid = group->gr_gid;
882 cur_arg += 2;
883 continue;
884 }
885
886 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
887 file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100893 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200894 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895
896 if (*(args[1]) == 0 || *(args[2]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901
902 facility = get_log_facility(args[2]);
903 if (facility < 0) {
904 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200905 err_code |= ERR_ALERT | ERR_FATAL;
906 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200907 }
908
909 level = 7; /* max syslog level = debug */
910 if (*(args[3])) {
911 level = get_log_level(args[3]);
912 if (level < 0) {
913 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200914 err_code |= ERR_ALERT | ERR_FATAL;
915 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 }
917 }
918
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200919 minlvl = 0; /* limit syslog level to this level (emerg) */
920 if (*(args[4])) {
921 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200923 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT | ERR_FATAL;
925 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 }
927 }
928
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100930 struct sockaddr_un *sk = str2sun(args[1]);
931 if (!sk) {
932 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
933 args[1], (int)sizeof(sk->sun_path) - 1);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100938 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100939 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100940 struct sockaddr_in *sk = str2sa(args[1]);
941 if (!sk) {
942 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100947 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100948 if (!logsrv.u.in.sin_port)
949 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951
952 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100953 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 global.logfac1 = facility;
955 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200956 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 global.logfac2 = facility;
961 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200962 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 else {
965 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200968 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100969 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
970 char *name;
971 int len;
972
973 if (global.log_send_hostname != NULL) {
974 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT;
976 goto out;
977 }
978
979 if (*(args[1]))
980 name = args[1];
981 else
982 name = hostname;
983
984 len = strlen(name);
985
986 /* We'll add a space after the name to respect the log format */
987 free(global.log_send_hostname);
988 global.log_send_hostname = malloc(len + 2);
989 snprintf(global.log_send_hostname, len + 2, "%s ", name);
990 }
Kevinm48936af2010-12-22 16:08:21 +0000991 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
992 if (*(args[1]) == 0) {
993 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
994 err_code |= ERR_ALERT | ERR_FATAL;
995 goto out;
996 }
997 free(global.log_tag);
998 global.log_tag = strdup(args[1]);
999 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001000 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1001 if (global.spread_checks != 0) {
1002 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT;
1004 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001005 }
1006 if (*(args[1]) == 0) {
1007 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
1011 global.spread_checks = atol(args[1]);
1012 if (global.spread_checks < 0 || global.spread_checks > 50) {
1013 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 }
1017 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001018 struct cfg_kw_list *kwl;
1019 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001020 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001021
1022 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1023 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1024 if (kwl->kw[index].section != CFG_GLOBAL)
1025 continue;
1026 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1027 /* prepare error message just in case */
1028 snprintf(trash, sizeof(trash),
1029 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001030 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1031 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001032 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001033 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001034 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001035 else if (rc > 0) {
1036 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_WARN;
1038 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001039 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001041 }
1042 }
1043 }
1044
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001046 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001048
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 out:
1050 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051}
1052
Willy Tarreau97cb7802010-01-03 20:23:58 +01001053/* Perform the most basic initialization of a proxy :
1054 * memset(), list_init(*), reset_timeouts(*).
1055 */
1056static void init_new_proxy(struct proxy *p)
1057{
1058 memset(p, 0, sizeof(struct proxy));
1059 LIST_INIT(&p->pendconns);
1060 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001061 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001062 LIST_INIT(&p->block_cond);
1063 LIST_INIT(&p->redirect_rules);
1064 LIST_INIT(&p->mon_fail_cond);
1065 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001066 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001067 LIST_INIT(&p->sticking_rules);
1068 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001069 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001070 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001071 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001072 LIST_INIT(&p->req_add);
1073 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001074
1075 /* Timeouts are defined as -1 */
1076 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001077 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001078}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001080void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001082 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 defproxy.mode = PR_MODE_TCP;
1084 defproxy.state = PR_STNEW;
1085 defproxy.maxconn = cfg_maxpconn;
1086 defproxy.conn_retries = CONN_RETRIES;
1087 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001088
1089 defproxy.defsrv.inter = DEF_CHKINTR;
1090 defproxy.defsrv.fastinter = 0;
1091 defproxy.defsrv.downinter = 0;
1092 defproxy.defsrv.rise = DEF_RISETIME;
1093 defproxy.defsrv.fall = DEF_FALLTIME;
1094 defproxy.defsrv.check_port = 0;
1095 defproxy.defsrv.maxqueue = 0;
1096 defproxy.defsrv.minconn = 0;
1097 defproxy.defsrv.maxconn = 0;
1098 defproxy.defsrv.slowstart = 0;
1099 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1100 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1101 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102}
1103
Willy Tarreauade5ec42010-01-28 19:33:49 +01001104
1105static int create_cond_regex_rule(const char *file, int line,
1106 struct proxy *px, int dir, int action, int flags,
1107 const char *cmd, const char *reg, const char *repl,
1108 const char **cond_start)
1109{
1110 regex_t *preg = NULL;
1111 const char *err;
1112 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001113 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001114
1115 if (px == &defproxy) {
1116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1117 err_code |= ERR_ALERT | ERR_FATAL;
1118 goto err;
1119 }
1120
1121 if (*reg == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
1127 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1128 err_code |= ERR_WARN;
1129
Willy Tarreau5321c422010-01-28 20:35:13 +01001130 if (cond_start &&
1131 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1132 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1133 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1134 file, line, cmd);
1135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto err;
1137 }
1138 }
1139 else if (cond_start && **cond_start) {
1140 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1141 file, line, cmd, *cond_start);
1142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto err;
1144 }
1145
1146 if (dir == ACL_DIR_REQ)
1147 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001148 else
1149 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001150
Willy Tarreauade5ec42010-01-28 19:33:49 +01001151 preg = calloc(1, sizeof(regex_t));
1152 if (!preg) {
1153 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1154 err_code = ERR_ALERT | ERR_FATAL;
1155 goto err;
1156 }
1157
1158 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1159 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1160 err_code = ERR_ALERT | ERR_FATAL;
1161 goto err;
1162 }
1163
1164 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001165 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001166 if (repl && err) {
1167 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1168 file, line, cmd, *err);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto err;
1171 }
1172
1173 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1174 err_code |= ERR_WARN;
1175
1176 return err_code;
1177 err:
1178 free(preg);
1179 return err_code;
1180}
1181
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001183 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001184 * Returns the error code, 0 if OK, or any combination of :
1185 * - ERR_ABORT: must abort ASAP
1186 * - ERR_FATAL: we can continue parsing but not start the service
1187 * - ERR_WARN: a warning has been emitted
1188 * - ERR_ALERT: an alert has been emitted
1189 * Only the two first ones can stop processing, the two others are just
1190 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001192int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1193{
1194 static struct peers *curpeers = NULL;
1195 struct peer *newpeer = NULL;
1196 const char *err;
1197 int err_code = 0;
1198
1199 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1200
1201 err = invalid_char(args[1]);
1202 if (err) {
1203 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1204 file, linenum, *err, args[0], args[1]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 }
1207
1208 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1209 /*
1210 * If there are two proxies with the same name only following
1211 * combinations are allowed:
1212 */
1213 if (strcmp(curpeers->id, args[1]) == 0) {
1214 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1215 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1216 err_code |= ERR_WARN;
1217 }
1218 }
1219
1220 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1221 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1222 err_code |= ERR_ALERT | ERR_ABORT;
1223 goto out;
1224 }
1225
1226 curpeers->next = peers;
1227 peers = curpeers;
1228 curpeers->conf.file = file;
1229 curpeers->conf.line = linenum;
1230 curpeers->last_change = now.tv_sec;
1231 curpeers->id = strdup(args[1]);
1232 }
1233 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1234 char *rport, *raddr;
1235 short realport = 0;
1236 struct sockaddr_in *sk;
1237
1238 if (!*args[2]) {
1239 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1240 file, linenum, args[0]);
1241 err_code |= ERR_ALERT | ERR_FATAL;
1242 goto out;
1243 }
1244
1245 err = invalid_char(args[1]);
1246 if (err) {
1247 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1248 file, linenum, *err, args[1]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252
1253 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1254 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1255 err_code |= ERR_ALERT | ERR_ABORT;
1256 goto out;
1257 }
1258
1259 /* the peers are linked backwards first */
1260 curpeers->count++;
1261 newpeer->next = curpeers->remote;
1262 curpeers->remote = newpeer;
1263 newpeer->peers = curpeers;
1264 newpeer->conf.file = file;
1265 newpeer->conf.line = linenum;
1266
1267 newpeer->last_change = now.tv_sec;
1268 newpeer->id = strdup(args[1]);
1269
1270 raddr = strdup(args[2]);
1271 rport = strchr(raddr, ':');
1272 if (rport) {
1273 *rport++ = 0;
1274 realport = atol(rport);
1275 }
1276 if (!realport) {
1277 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
1280 }
1281
1282 sk = str2sa(raddr);
1283 free(raddr);
1284 if (!sk) {
1285 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289 newpeer->addr = *sk;
1290 newpeer->addr.sin_port = htons(realport);
1291
1292 if (strcmp(newpeer->id, localpeer) == 0) {
1293 /* Current is local peer, it define a frontend */
1294 newpeer->local = 1;
1295
1296 if (!curpeers->peers_fe) {
1297 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1298 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1299 err_code |= ERR_ALERT | ERR_ABORT;
1300 goto out;
1301 }
1302 curpeers->peers_fe->parent = curpeers;
1303
1304 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1305 LIST_INIT(&(curpeers->peers_fe)->acl);
1306 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1307 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1308 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1309 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1310 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1311 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1312
1313 proxy_reset_timeouts(curpeers->peers_fe);
1314
1315 curpeers->peers_fe->last_change = now.tv_sec;
1316 curpeers->peers_fe->id = strdup(args[1]);
1317 curpeers->peers_fe->cap = PR_CAP_FE;
1318 curpeers->peers_fe->maxconn = 65000;
1319 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1320 curpeers->peers_fe->timeout.connect = 5000;
1321 curpeers->peers_fe->accept = peer_accept;
1322 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
1323 if (!str2listener(args[2], curpeers->peers_fe)) {
1324 err_code |= ERR_FATAL;
1325 goto out;
1326 }
1327 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1328 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1329 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1330 curpeers->peers_fe->listen->accept = session_accept;
1331 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1332 curpeers->peers_fe->listen->handler = process_session;
1333 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1334 }
1335 }
1336 } /* neither "peer" nor "peers" */
1337 else if (*args[0] != 0) {
1338 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
1341 }
1342
1343out:
1344 return err_code;
1345}
1346
1347
Willy Tarreau3842f002009-06-14 11:39:52 +02001348int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349{
1350 static struct proxy *curproxy = NULL;
1351 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001352 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001353 int rc;
1354 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001355 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001356 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357
Willy Tarreau977b8e42006-12-29 14:19:17 +01001358 if (!strcmp(args[0], "listen"))
1359 rc = PR_CAP_LISTEN;
1360 else if (!strcmp(args[0], "frontend"))
1361 rc = PR_CAP_FE | PR_CAP_RS;
1362 else if (!strcmp(args[0], "backend"))
1363 rc = PR_CAP_BE | PR_CAP_RS;
1364 else if (!strcmp(args[0], "ruleset"))
1365 rc = PR_CAP_RS;
1366 else
1367 rc = PR_CAP_NONE;
1368
1369 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 if (!*args[1]) {
1371 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1372 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1373 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_ALERT | ERR_ABORT;
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001377
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001378 err = invalid_char(args[1]);
1379 if (err) {
1380 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1381 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001383 }
1384
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001385 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1386 /*
1387 * If there are two proxies with the same name only following
1388 * combinations are allowed:
1389 *
1390 * listen backend frontend ruleset
1391 * listen - - - -
1392 * backend - - OK -
1393 * frontend - OK - -
1394 * ruleset - - - -
1395 */
1396
1397 if (!strcmp(curproxy->id, args[1]) &&
1398 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1399 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001400 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1401 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1402 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001403 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001404 }
1405 }
1406
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1408 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001409 err_code |= ERR_ALERT | ERR_ABORT;
1410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001412
Willy Tarreau97cb7802010-01-03 20:23:58 +01001413 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 curproxy->next = proxy;
1415 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001416 curproxy->conf.file = file;
1417 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001418 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001420 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421
1422 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001424 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001425 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001426 err_code |= ERR_FATAL;
1427 goto out;
1428 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001429 new = curproxy->listen;
1430 while (new != last) {
1431 new->conf.file = file;
1432 new->conf.line = linenum;
1433 new = new->next;
1434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 global.maxsock++;
1436 }
1437
1438 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001439 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001440 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001441
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001444 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001445 curproxy->no_options = defproxy.no_options;
1446 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001447 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001448 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001449 curproxy->except_net = defproxy.except_net;
1450 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001451 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001452 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001454 if (defproxy.fwdfor_hdr_len) {
1455 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1456 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1457 }
1458
Willy Tarreaub86db342009-11-30 11:50:16 +01001459 if (defproxy.orgto_hdr_len) {
1460 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1461 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1462 }
1463
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 if (curproxy->cap & PR_CAP_FE) {
1465 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001466 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001467 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001468
1469 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001470 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1471 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472
1473 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475
Willy Tarreau977b8e42006-12-29 14:19:17 +01001476 if (curproxy->cap & PR_CAP_BE) {
1477 curproxy->fullconn = defproxy.fullconn;
1478 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001480 if (defproxy.check_req) {
1481 curproxy->check_req = calloc(1, defproxy.check_len);
1482 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1483 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001484 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485
Willy Tarreau977b8e42006-12-29 14:19:17 +01001486 if (defproxy.cookie_name)
1487 curproxy->cookie_name = strdup(defproxy.cookie_name);
1488 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001489 if (defproxy.cookie_domain)
1490 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001491
Willy Tarreau31936852010-10-06 16:59:56 +02001492 if (defproxy.cookie_maxidle)
1493 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1494
1495 if (defproxy.cookie_maxlife)
1496 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1497
Emeric Brun647caf12009-06-30 17:57:00 +02001498 if (defproxy.rdp_cookie_name)
1499 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1500 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1501
Willy Tarreau01732802007-11-01 22:48:15 +01001502 if (defproxy.url_param_name)
1503 curproxy->url_param_name = strdup(defproxy.url_param_name);
1504 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001505
Benoitaffb4812009-03-25 13:02:10 +01001506 if (defproxy.hh_name)
1507 curproxy->hh_name = strdup(defproxy.hh_name);
1508 curproxy->hh_len = defproxy.hh_len;
1509 curproxy->hh_match_domain = defproxy.hh_match_domain;
1510
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001511 if (defproxy.iface_name)
1512 curproxy->iface_name = strdup(defproxy.iface_name);
1513 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001516 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001517 if (defproxy.capture_name)
1518 curproxy->capture_name = strdup(defproxy.capture_name);
1519 curproxy->capture_namelen = defproxy.capture_namelen;
1520 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001522
Willy Tarreau977b8e42006-12-29 14:19:17 +01001523 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001524 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001525 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001526 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001527 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001528 curproxy->uri_auth = defproxy.uri_auth;
1529 curproxy->mon_net = defproxy.mon_net;
1530 curproxy->mon_mask = defproxy.mon_mask;
1531 if (defproxy.monitor_uri)
1532 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1533 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001534 if (defproxy.defbe.name)
1535 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001536 }
1537
1538 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001539 curproxy->timeout.connect = defproxy.timeout.connect;
1540 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001541 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001542 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001543 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001544 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001545 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001546 curproxy->source_addr = defproxy.source_addr;
1547 }
1548
Willy Tarreaubaaee002006-06-26 02:48:02 +02001549 curproxy->mode = defproxy.mode;
1550 curproxy->logfac1 = defproxy.logfac1;
1551 curproxy->logsrv1 = defproxy.logsrv1;
1552 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001553 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 curproxy->logfac2 = defproxy.logfac2;
1555 curproxy->logsrv2 = defproxy.logsrv2;
1556 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001557 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001559 curproxy->conf.used_listener_id = EB_ROOT;
1560 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001561
Willy Tarreau93893792009-07-23 13:19:11 +02001562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 }
1564 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1565 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001566 /* FIXME-20070101: we should do this too at the end of the
1567 * config parsing to free all default values.
1568 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001569 free(defproxy.check_req);
1570 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001571 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001572 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001573 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001574 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001575 free(defproxy.capture_name);
1576 free(defproxy.monitor_uri);
1577 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001578 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001579 free(defproxy.fwdfor_hdr_name);
1580 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001581 free(defproxy.orgto_hdr_name);
1582 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001583
Willy Tarreaua534fea2008-08-03 12:19:50 +02001584 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001585 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001586
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 /* we cannot free uri_auth because it might already be used */
1588 init_default_instance();
1589 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 }
1593 else if (curproxy == NULL) {
1594 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 }
1598
Willy Tarreau977b8e42006-12-29 14:19:17 +01001599
1600 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001602 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001603 int cur_arg;
1604
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 if (curproxy == &defproxy) {
1606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001607 err_code |= ERR_ALERT | ERR_FATAL;
1608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001610 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001611 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612
Emeric Bruned760922010-10-22 17:59:25 +02001613 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001614 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001619
1620 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001621
1622 /* NOTE: the following line might create several listeners if there
1623 * are comma-separated IPs or port ranges. So all further processing
1624 * will have to be applied to all listeners created after last_listen.
1625 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001626 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
1629 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001630
Willy Tarreau90a570f2009-10-04 20:54:54 +02001631 new_listen = curproxy->listen;
1632 while (new_listen != last_listen) {
1633 new_listen->conf.file = file;
1634 new_listen->conf.line = linenum;
1635 new_listen = new_listen->next;
1636 }
1637
Emeric Bruned760922010-10-22 17:59:25 +02001638 /* Set default global rights and owner for unix bind */
1639 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1640 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1641 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001642 cur_arg = 2;
1643 while (*(args[cur_arg])) {
1644 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1645#ifdef SO_BINDTODEVICE
1646 struct listener *l;
1647
Emeric Bruned760922010-10-22 17:59:25 +02001648 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1649 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1650 file, linenum, args[0], args[cur_arg]);
1651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
1653 }
1654
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001655 if (!*args[cur_arg + 1]) {
1656 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1657 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001658 err_code |= ERR_ALERT | ERR_FATAL;
1659 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001660 }
1661
1662 for (l = curproxy->listen; l != last_listen; l = l->next)
1663 l->interface = strdup(args[cur_arg + 1]);
1664
1665 global.last_checks |= LSTCHK_NETADM;
1666
1667 cur_arg += 2;
1668 continue;
1669#else
1670 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1671 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001672 err_code |= ERR_ALERT | ERR_FATAL;
1673 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001674#endif
1675 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001676 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1677#ifdef TCP_MAXSEG
1678 struct listener *l;
1679 int mss;
1680
Emeric Bruned760922010-10-22 17:59:25 +02001681 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1682 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1683 file, linenum, args[0], args[cur_arg]);
1684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
1686 }
1687
Willy Tarreaube1b9182009-06-14 18:48:19 +02001688 if (!*args[cur_arg + 1]) {
1689 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1690 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001691 err_code |= ERR_ALERT | ERR_FATAL;
1692 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001693 }
1694
Willy Tarreau48a7e722010-12-24 15:26:39 +01001695 mss = atoi(args[cur_arg + 1]);
1696 if (!mss || abs(mss) > 65535) {
1697 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001698 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001701 }
1702
1703 for (l = curproxy->listen; l != last_listen; l = l->next)
1704 l->maxseg = mss;
1705
1706 cur_arg += 2;
1707 continue;
1708#else
1709 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1710 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001713#endif
1714 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001715
1716 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1717#ifdef TCP_DEFER_ACCEPT
1718 struct listener *l;
1719
1720 for (l = curproxy->listen; l != last_listen; l = l->next)
1721 l->options |= LI_O_DEF_ACCEPT;
1722
1723 cur_arg ++;
1724 continue;
1725#else
1726 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1727 file, linenum, args[0], args[cur_arg]);
1728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730#endif
1731 }
1732
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001733 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001734#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001735 struct listener *l;
1736
Emeric Bruned760922010-10-22 17:59:25 +02001737 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1738 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1739 file, linenum, args[0], args[cur_arg]);
1740 err_code |= ERR_ALERT | ERR_FATAL;
1741 goto out;
1742 }
1743
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001744 for (l = curproxy->listen; l != last_listen; l = l->next)
1745 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001746
1747 cur_arg ++;
1748 continue;
1749#else
1750 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1751 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001754#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001755 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001756
Willy Tarreau8a956912010-10-15 14:27:08 +02001757 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1758 struct listener *l;
1759
1760 for (l = curproxy->listen; l != last_listen; l = l->next)
1761 l->options |= LI_O_ACC_PROXY;
1762
1763 cur_arg ++;
1764 continue;
1765 }
1766
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001767 if (!strcmp(args[cur_arg], "name")) {
1768 struct listener *l;
1769
1770 for (l = curproxy->listen; l != last_listen; l = l->next)
1771 l->name = strdup(args[cur_arg + 1]);
1772
1773 cur_arg += 2;
1774 continue;
1775 }
1776
1777 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001778 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001779 struct listener *l;
1780
1781 if (curproxy->listen->next != last_listen) {
1782 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1783 file, linenum, args[cur_arg]);
1784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
1786 }
1787
1788 if (!*args[cur_arg + 1]) {
1789 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1790 file, linenum, args[cur_arg]);
1791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
1793 }
1794
1795 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001796 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001797
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001798 if (curproxy->listen->luid <= 0) {
1799 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001800 file, linenum);
1801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
1803 }
1804
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001805 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1806 if (node) {
1807 l = container_of(node, struct listener, conf.id);
1808 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1809 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
1812 }
1813 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1814
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001815 cur_arg += 2;
1816 continue;
1817 }
1818
Emeric Bruned760922010-10-22 17:59:25 +02001819 if (!strcmp(args[cur_arg], "mode")) {
1820
1821 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1822 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1823 file, linenum, args[0], args[cur_arg]);
1824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827
1828 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1829
1830 cur_arg += 2;
1831 continue;
1832 }
1833
1834 if (!strcmp(args[cur_arg], "uid")) {
1835
1836 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1837 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1838 file, linenum, args[0], args[cur_arg]);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842
1843 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1844 cur_arg += 2;
1845 continue;
1846 }
1847
1848 if (!strcmp(args[cur_arg], "gid")) {
1849
1850 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1851 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1852 file, linenum, args[0], args[cur_arg]);
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856
1857 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1858 cur_arg += 2;
1859 continue;
1860 }
1861
1862 if (!strcmp(args[cur_arg], "user")) {
1863 struct passwd *user;
1864
1865 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1866 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1867 file, linenum, args[0], args[cur_arg]);
1868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
1870 }
1871 user = getpwnam(args[cur_arg + 1]);
1872 if (!user) {
1873 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1874 file, linenum, args[0], args[cur_arg + 1 ]);
1875 err_code |= ERR_ALERT | ERR_FATAL;
1876 goto out;
1877 }
1878
1879 curproxy->listen->perm.ux.uid = user->pw_uid;
1880 cur_arg += 2;
1881 continue;
1882 }
1883
1884 if (!strcmp(args[cur_arg], "group")) {
1885 struct group *group;
1886
1887 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1888 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1889 file, linenum, args[0], args[cur_arg]);
1890 err_code |= ERR_ALERT | ERR_FATAL;
1891 goto out;
1892 }
1893 group = getgrnam(args[cur_arg + 1]);
1894 if (!group) {
1895 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1896 file, linenum, args[0], args[cur_arg + 1 ]);
1897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
1899 }
1900
1901 curproxy->listen->perm.ux.gid = group->gr_gid;
1902 cur_arg += 2;
1903 continue;
1904 }
1905
Willy Tarreau8a956912010-10-15 14:27:08 +02001906 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001907 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_ALERT | ERR_FATAL;
1909 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 }
1914 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1915 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1916 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1917 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001918 err_code |= ERR_ALERT | ERR_FATAL;
1919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001921 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001923
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 /* flush useless bits */
1925 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001928 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001929 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001930 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001931
Willy Tarreau1c47f852006-07-09 08:22:27 +02001932 if (!*args[1]) {
1933 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1934 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001937 }
1938
Willy Tarreaua534fea2008-08-03 12:19:50 +02001939 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001940 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001941 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001942 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001943 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1944
Willy Tarreau93893792009-07-23 13:19:11 +02001945 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1948 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1949 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1950 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1951 else {
1952 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 }
1956 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001957 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001958 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001959
1960 if (curproxy == &defproxy) {
1961 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1962 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001963 err_code |= ERR_ALERT | ERR_FATAL;
1964 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001965 }
1966
1967 if (!*args[1]) {
1968 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1969 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001970 err_code |= ERR_ALERT | ERR_FATAL;
1971 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001972 }
1973
1974 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001975 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001976
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001977 if (curproxy->uuid <= 0) {
1978 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001979 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001982 }
1983
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001984 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1985 if (node) {
1986 struct proxy *target = container_of(node, struct proxy, conf.id);
1987 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1988 file, linenum, proxy_type_str(curproxy), curproxy->id,
1989 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1990 err_code |= ERR_ALERT | ERR_FATAL;
1991 goto out;
1992 }
1993 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001994 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001995 else if (!strcmp(args[0], "description")) {
1996 int i, len=0;
1997 char *d;
1998
Cyril Bonté99ed3272010-01-24 23:29:44 +01001999 if (curproxy == &defproxy) {
2000 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2001 file, linenum, args[0]);
2002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
2004 }
2005
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002006 if (!*args[1]) {
2007 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2008 file, linenum, args[0]);
2009 return -1;
2010 }
2011
2012 for(i=1; *args[i]; i++)
2013 len += strlen(args[i])+1;
2014
2015 d = (char *)calloc(1, len);
2016 curproxy->desc = d;
2017
2018 d += sprintf(d, "%s", args[1]);
2019 for(i=2; *args[i]; i++)
2020 d += sprintf(d, " %s", args[i]);
2021
2022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002023 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2024 curproxy->state = PR_STSTOPPED;
2025 }
2026 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2027 curproxy->state = PR_STNEW;
2028 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002029 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2030 int cur_arg = 1;
2031 unsigned int set = 0;
2032
2033 while (*args[cur_arg]) {
2034 int u;
2035 if (strcmp(args[cur_arg], "all") == 0) {
2036 set = 0;
2037 break;
2038 }
2039 else if (strcmp(args[cur_arg], "odd") == 0) {
2040 set |= 0x55555555;
2041 }
2042 else if (strcmp(args[cur_arg], "even") == 0) {
2043 set |= 0xAAAAAAAA;
2044 }
2045 else {
2046 u = str2uic(args[cur_arg]);
2047 if (u < 1 || u > 32) {
2048 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2049 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002052 }
2053 if (u > global.nbproc) {
2054 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2055 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002057 }
2058 set |= 1 << (u - 1);
2059 }
2060 cur_arg++;
2061 }
2062 curproxy->bind_proc = set;
2063 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002064 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002065 if (curproxy == &defproxy) {
2066 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_ALERT | ERR_FATAL;
2068 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002069 }
2070
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002071 err = invalid_char(args[1]);
2072 if (err) {
2073 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2074 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002075 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002076 }
2077
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002078 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2079 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2080 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002081 err_code |= ERR_ALERT | ERR_FATAL;
2082 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002083 }
2084 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2086 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087
Willy Tarreau977b8e42006-12-29 14:19:17 +01002088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002089 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090
Willy Tarreaubaaee002006-06-26 02:48:02 +02002091 if (*(args[1]) == 0) {
2092 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2093 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002097
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002098 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002099 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002100 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002101 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002102 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 curproxy->cookie_name = strdup(args[1]);
2104 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002105
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 cur_arg = 2;
2107 while (*(args[cur_arg])) {
2108 if (!strcmp(args[cur_arg], "rewrite")) {
2109 curproxy->options |= PR_O_COOK_RW;
2110 }
2111 else if (!strcmp(args[cur_arg], "indirect")) {
2112 curproxy->options |= PR_O_COOK_IND;
2113 }
2114 else if (!strcmp(args[cur_arg], "insert")) {
2115 curproxy->options |= PR_O_COOK_INS;
2116 }
2117 else if (!strcmp(args[cur_arg], "nocache")) {
2118 curproxy->options |= PR_O_COOK_NOC;
2119 }
2120 else if (!strcmp(args[cur_arg], "postonly")) {
2121 curproxy->options |= PR_O_COOK_POST;
2122 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002123 else if (!strcmp(args[cur_arg], "preserve")) {
2124 curproxy->options2 |= PR_O2_COOK_PSV;
2125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 else if (!strcmp(args[cur_arg], "prefix")) {
2127 curproxy->options |= PR_O_COOK_PFX;
2128 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002129 else if (!strcmp(args[cur_arg], "domain")) {
2130 if (!*args[cur_arg + 1]) {
2131 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2132 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002133 err_code |= ERR_ALERT | ERR_FATAL;
2134 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002135 }
2136
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002137 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002138 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002139 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2140 " dots nor does not start with a dot."
2141 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002142 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002143 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002144 }
2145
2146 err = invalid_domainchar(args[cur_arg + 1]);
2147 if (err) {
2148 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2149 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002150 err_code |= ERR_ALERT | ERR_FATAL;
2151 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002152 }
2153
Willy Tarreau68a897b2009-12-03 23:28:34 +01002154 if (!curproxy->cookie_domain) {
2155 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2156 } else {
2157 /* one domain was already specified, add another one by
2158 * building the string which will be returned along with
2159 * the cookie.
2160 */
2161 char *new_ptr;
2162 int new_len = strlen(curproxy->cookie_domain) +
2163 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2164 new_ptr = malloc(new_len);
2165 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2166 free(curproxy->cookie_domain);
2167 curproxy->cookie_domain = new_ptr;
2168 }
Willy Tarreau31936852010-10-06 16:59:56 +02002169 cur_arg++;
2170 }
2171 else if (!strcmp(args[cur_arg], "maxidle")) {
2172 unsigned int maxidle;
2173 const char *res;
2174
2175 if (!*args[cur_arg + 1]) {
2176 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2177 file, linenum, args[cur_arg]);
2178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
2180 }
2181
2182 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2183 if (res) {
2184 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2185 file, linenum, *res, args[cur_arg]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189 curproxy->cookie_maxidle = maxidle;
2190 cur_arg++;
2191 }
2192 else if (!strcmp(args[cur_arg], "maxlife")) {
2193 unsigned int maxlife;
2194 const char *res;
2195
2196 if (!*args[cur_arg + 1]) {
2197 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2198 file, linenum, args[cur_arg]);
2199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
2201 }
2202
2203 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2204 if (res) {
2205 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2206 file, linenum, *res, args[cur_arg]);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002211 cur_arg++;
2212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002214 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 }
2219 cur_arg++;
2220 }
2221 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2222 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2223 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 }
2226
2227 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2228 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2229 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002232
2233 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2234 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2235 file, linenum);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002239 else if (!strcmp(args[0], "persist")) { /* persist */
2240 if (*(args[1]) == 0) {
2241 Alert("parsing [%s:%d] : missing persist method.\n",
2242 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002245 }
2246
2247 if (!strncmp(args[1], "rdp-cookie", 10)) {
2248 curproxy->options2 |= PR_O2_RDPC_PRST;
2249
Emeric Brunb982a3d2010-01-04 15:45:53 +01002250 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002251 const char *beg, *end;
2252
2253 beg = args[1] + 11;
2254 end = strchr(beg, ')');
2255
2256 if (!end || end == beg) {
2257 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002261 }
2262
2263 free(curproxy->rdp_cookie_name);
2264 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2265 curproxy->rdp_cookie_len = end-beg;
2266 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002267 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002268 free(curproxy->rdp_cookie_name);
2269 curproxy->rdp_cookie_name = strdup("msts");
2270 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2271 }
2272 else { /* syntax */
2273 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2274 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002277 }
2278 }
2279 else {
2280 Alert("parsing [%s:%d] : unknown persist method.\n",
2281 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002284 }
2285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002287 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002289 if (curproxy == &defproxy) {
2290 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002297
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002299 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 }
2304 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002305 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 curproxy->appsession_name = strdup(args[1]);
2307 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2308 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002309 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2310 if (err) {
2311 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2312 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002315 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002316 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002317
Willy Tarreau51041c72007-09-09 21:56:53 +02002318 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002320 err_code |= ERR_ALERT | ERR_ABORT;
2321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002323
2324 cur_arg = 6;
2325 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002326 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2327 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002328 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002329 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002330 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002331 } else if (!strcmp(args[cur_arg], "prefix")) {
2332 curproxy->options2 |= PR_O2_AS_PFX;
2333 } else if (!strcmp(args[cur_arg], "mode")) {
2334 if (!*args[cur_arg + 1]) {
2335 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2336 file, linenum, args[0], args[cur_arg]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
2341 cur_arg++;
2342 if (!strcmp(args[cur_arg], "query-string")) {
2343 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2344 curproxy->options2 |= PR_O2_AS_M_QS;
2345 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2346 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2347 curproxy->options2 |= PR_O2_AS_M_PP;
2348 } else {
2349 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
2353 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002354 cur_arg++;
2355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 } /* Url App Session */
2357 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002358 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002360
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002362 if (curproxy == &defproxy) {
2363 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2364 err_code |= ERR_ALERT | ERR_FATAL;
2365 goto out;
2366 }
2367
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 if (*(args[4]) == 0) {
2369 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002374 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 curproxy->capture_name = strdup(args[2]);
2376 curproxy->capture_namelen = strlen(curproxy->capture_name);
2377 curproxy->capture_len = atol(args[4]);
2378 if (curproxy->capture_len >= CAPTURE_LEN) {
2379 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2380 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 curproxy->capture_len = CAPTURE_LEN - 1;
2383 }
2384 curproxy->to_log |= LW_COOKIE;
2385 }
2386 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2387 struct cap_hdr *hdr;
2388
2389 if (curproxy == &defproxy) {
2390 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394
2395 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2396 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2397 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401
2402 hdr = calloc(sizeof(struct cap_hdr), 1);
2403 hdr->next = curproxy->req_cap;
2404 hdr->name = strdup(args[3]);
2405 hdr->namelen = strlen(args[3]);
2406 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002407 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 hdr->index = curproxy->nb_req_cap++;
2409 curproxy->req_cap = hdr;
2410 curproxy->to_log |= LW_REQHDR;
2411 }
2412 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2413 struct cap_hdr *hdr;
2414
2415 if (curproxy == &defproxy) {
2416 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 }
2420
2421 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2422 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2423 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 }
2427 hdr = calloc(sizeof(struct cap_hdr), 1);
2428 hdr->next = curproxy->rsp_cap;
2429 hdr->name = strdup(args[3]);
2430 hdr->namelen = strlen(args[3]);
2431 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002432 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 hdr->index = curproxy->nb_rsp_cap++;
2434 curproxy->rsp_cap = hdr;
2435 curproxy->to_log |= LW_RSPHDR;
2436 }
2437 else {
2438 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2439 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002445 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002447
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 if (*(args[1]) == 0) {
2449 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 }
2454 curproxy->conn_retries = atol(args[1]);
2455 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002456 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
2457 struct req_acl_rule *req_acl;
2458
2459 if (curproxy == &defproxy) {
2460 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
2465
2466 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2467 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2468 file, linenum, args[0]);
2469 err_code |= ERR_WARN;
2470 }
2471
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002472 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002473
2474 if (!req_acl) {
2475 err_code |= ERR_ALERT | ERR_ABORT;
2476 goto out;
2477 }
2478
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002479 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002480 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2481 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002482 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002483 if (curproxy == &defproxy) {
2484 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002487 }
2488
Willy Tarreauef6494c2010-01-28 17:12:36 +01002489 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002490 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002494 }
2495
Willy Tarreauef6494c2010-01-28 17:12:36 +01002496 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002497 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2498 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002501 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002502
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002503 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002504 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002505 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002506 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002507 struct redirect_rule *rule;
2508 int cur_arg;
2509 int type = REDIRECT_TYPE_NONE;
2510 int code = 302;
2511 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002512 char *cookie = NULL;
2513 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002514 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002515
Cyril Bonté99ed3272010-01-24 23:29:44 +01002516 if (curproxy == &defproxy) {
2517 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002522 cur_arg = 1;
2523 while (*(args[cur_arg])) {
2524 if (!strcmp(args[cur_arg], "location")) {
2525 if (!*args[cur_arg + 1]) {
2526 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2527 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002530 }
2531
2532 type = REDIRECT_TYPE_LOCATION;
2533 cur_arg++;
2534 destination = args[cur_arg];
2535 }
2536 else if (!strcmp(args[cur_arg], "prefix")) {
2537 if (!*args[cur_arg + 1]) {
2538 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2539 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002542 }
2543
2544 type = REDIRECT_TYPE_PREFIX;
2545 cur_arg++;
2546 destination = args[cur_arg];
2547 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002548 else if (!strcmp(args[cur_arg], "set-cookie")) {
2549 if (!*args[cur_arg + 1]) {
2550 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2551 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002554 }
2555
2556 cur_arg++;
2557 cookie = args[cur_arg];
2558 cookie_set = 1;
2559 }
2560 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2561 if (!*args[cur_arg + 1]) {
2562 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2563 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002566 }
2567
2568 cur_arg++;
2569 cookie = args[cur_arg];
2570 cookie_set = 0;
2571 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002572 else if (!strcmp(args[cur_arg],"code")) {
2573 if (!*args[cur_arg + 1]) {
2574 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2575 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002578 }
2579 cur_arg++;
2580 code = atol(args[cur_arg]);
2581 if (code < 301 || code > 303) {
2582 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2583 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002586 }
2587 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002588 else if (!strcmp(args[cur_arg],"drop-query")) {
2589 flags |= REDIRECT_FLAG_DROP_QS;
2590 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002591 else if (!strcmp(args[cur_arg],"append-slash")) {
2592 flags |= REDIRECT_FLAG_APPEND_SLASH;
2593 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002594 else if (strcmp(args[cur_arg], "if") == 0 ||
2595 strcmp(args[cur_arg], "unless") == 0) {
2596 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2597 if (!cond) {
2598 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2599 file, linenum, args[0]);
2600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
2602 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002603 break;
2604 }
2605 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002606 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002607 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002610 }
2611 cur_arg++;
2612 }
2613
2614 if (type == REDIRECT_TYPE_NONE) {
2615 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2616 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002619 }
2620
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002621 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2622 rule->cond = cond;
2623 rule->rdr_str = strdup(destination);
2624 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002625 if (cookie) {
2626 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002627 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002628 */
2629 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002630 if (cookie_set) {
2631 rule->cookie_str = malloc(rule->cookie_len + 10);
2632 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2633 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2634 rule->cookie_len += 9;
2635 } else {
2636 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002637 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002638 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2639 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002640 }
2641 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002642 rule->type = type;
2643 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002644 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002645 LIST_INIT(&rule->list);
2646 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002647 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002648 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002649 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002650 struct switching_rule *rule;
2651
Willy Tarreaub099aca2008-10-12 17:26:37 +02002652 if (curproxy == &defproxy) {
2653 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002656 }
2657
Willy Tarreau55ea7572007-06-17 19:56:27 +02002658 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002659 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002660
2661 if (*(args[1]) == 0) {
2662 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002665 }
2666
Willy Tarreauef6494c2010-01-28 17:12:36 +01002667 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002668 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002672 }
2673
Willy Tarreauef6494c2010-01-28 17:12:36 +01002674 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002675 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002676 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002679 }
2680
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002681 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002682
Willy Tarreau55ea7572007-06-17 19:56:27 +02002683 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2684 rule->cond = cond;
2685 rule->be.name = strdup(args[1]);
2686 LIST_INIT(&rule->list);
2687 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2688 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002689 else if ((!strcmp(args[0], "force-persist")) ||
2690 (!strcmp(args[0], "ignore-persist"))) {
2691 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002692
2693 if (curproxy == &defproxy) {
2694 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2695 err_code |= ERR_ALERT | ERR_FATAL;
2696 goto out;
2697 }
2698
2699 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2700 err_code |= ERR_WARN;
2701
Willy Tarreauef6494c2010-01-28 17:12:36 +01002702 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002703 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2704 file, linenum, args[0]);
2705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
2707 }
2708
Willy Tarreauef6494c2010-01-28 17:12:36 +01002709 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002710 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2711 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
2714 }
2715
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002716 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002717
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002718 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002719 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002720 if (!strcmp(args[0], "force-persist")) {
2721 rule->type = PERSIST_TYPE_FORCE;
2722 } else {
2723 rule->type = PERSIST_TYPE_IGNORE;
2724 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002725 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002726 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002727 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002728 else if (!strcmp(args[0], "stick-table")) {
2729 int myidx = 1;
2730
Emeric Brun32da3c42010-09-23 18:39:19 +02002731 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002732 curproxy->table.type = (unsigned int)-1;
2733 while (*args[myidx]) {
2734 const char *err;
2735
2736 if (strcmp(args[myidx], "size") == 0) {
2737 myidx++;
2738 if (!*(args[myidx])) {
2739 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2740 file, linenum, args[myidx-1]);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2745 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2746 file, linenum, *err, args[myidx-1]);
2747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
2749 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002750 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002751 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002752 else if (strcmp(args[myidx], "peers") == 0) {
2753 myidx++;
2754 if (!*(args[myidx])) {
2755 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2756 file, linenum, args[myidx-1]);
2757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
2759 }
2760 curproxy->table.peers.name = strdup(args[myidx++]);
2761 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002762 else if (strcmp(args[myidx], "expire") == 0) {
2763 myidx++;
2764 if (!*(args[myidx])) {
2765 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2766 file, linenum, args[myidx-1]);
2767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
2769 }
2770 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2771 if (err) {
2772 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2773 file, linenum, *err, args[myidx-1]);
2774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
2776 }
2777 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002778 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002779 }
2780 else if (strcmp(args[myidx], "nopurge") == 0) {
2781 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002782 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002783 }
2784 else if (strcmp(args[myidx], "type") == 0) {
2785 myidx++;
2786 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2787 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2788 file, linenum, args[myidx]);
2789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
2791 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002792 /* myidx already points to next arg */
2793 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002794 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002795 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002796 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002797
2798 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002799 nw = args[myidx];
2800 while (*nw) {
2801 /* the "store" keyword supports a comma-separated list */
2802 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002803 sa = NULL; /* store arg */
2804 while (*nw && *nw != ',') {
2805 if (*nw == '(') {
2806 *nw = 0;
2807 sa = ++nw;
2808 while (*nw != ')') {
2809 if (!*nw) {
2810 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2811 file, linenum, args[0], cw);
2812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
2814 }
2815 nw++;
2816 }
2817 *nw = '\0';
2818 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002819 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002820 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002821 if (*nw)
2822 *nw++ = '\0';
2823 type = stktable_get_data_type(cw);
2824 if (type < 0) {
2825 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2826 file, linenum, args[0], cw);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829 }
Willy Tarreauac782882010-06-20 10:41:54 +02002830
2831 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2832 switch (err) {
2833 case PE_NONE: break;
2834 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002835 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2836 file, linenum, args[0], cw);
2837 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002838 break;
2839
2840 case PE_ARG_MISSING:
2841 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2842 file, linenum, args[0], cw);
2843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
2845
2846 case PE_ARG_NOT_USED:
2847 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2848 file, linenum, args[0], cw);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851
2852 default:
2853 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2854 file, linenum, args[0], cw);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002857 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002858 }
2859 myidx++;
2860 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002861 else {
2862 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2863 file, linenum, args[myidx]);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002866 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002867 }
2868
2869 if (!curproxy->table.size) {
2870 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2871 file, linenum);
2872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
2874 }
2875
2876 if (curproxy->table.type == (unsigned int)-1) {
2877 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2878 file, linenum);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882 }
2883 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002884 struct sticking_rule *rule;
2885 struct pattern_expr *expr;
2886 int myidx = 0;
2887 const char *name = NULL;
2888 int flags;
2889
2890 if (curproxy == &defproxy) {
2891 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
2894 }
2895
2896 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2897 err_code |= ERR_WARN;
2898 goto out;
2899 }
2900
2901 myidx++;
2902 if ((strcmp(args[myidx], "store") == 0) ||
2903 (strcmp(args[myidx], "store-request") == 0)) {
2904 myidx++;
2905 flags = STK_IS_STORE;
2906 }
2907 else if (strcmp(args[myidx], "store-response") == 0) {
2908 myidx++;
2909 flags = STK_IS_STORE | STK_ON_RSP;
2910 }
2911 else if (strcmp(args[myidx], "match") == 0) {
2912 myidx++;
2913 flags = STK_IS_MATCH;
2914 }
2915 else if (strcmp(args[myidx], "on") == 0) {
2916 myidx++;
2917 flags = STK_IS_MATCH | STK_IS_STORE;
2918 }
2919 else {
2920 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923 }
2924
2925 if (*(args[myidx]) == 0) {
2926 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930
Emeric Brun485479d2010-09-23 18:02:19 +02002931 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002932 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002933 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
2936 }
2937
2938 if (flags & STK_ON_RSP) {
2939 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2940 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2941 file, linenum, args[0], expr->fetch->kw);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945 } else {
2946 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2947 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2948 file, linenum, args[0], expr->fetch->kw);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 }
2953
2954 if (strcmp(args[myidx], "table") == 0) {
2955 myidx++;
2956 name = args[myidx++];
2957 }
2958
Willy Tarreauef6494c2010-01-28 17:12:36 +01002959 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2960 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002961 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2962 file, linenum, args[0]);
2963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
2965 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002966 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002967 else if (*(args[myidx])) {
2968 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2969 file, linenum, args[0], args[myidx]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
Emeric Brun97679e72010-09-23 17:56:44 +02002973 if (flags & STK_ON_RSP)
2974 err_code |= warnif_cond_requires_req(cond, file, linenum);
2975 else
2976 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002977
Emeric Brunb982a3d2010-01-04 15:45:53 +01002978 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2979 rule->cond = cond;
2980 rule->expr = expr;
2981 rule->flags = flags;
2982 rule->table.name = name ? strdup(name) : NULL;
2983 LIST_INIT(&rule->list);
2984 if (flags & STK_ON_RSP)
2985 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2986 else
2987 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002990 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002992
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2994 curproxy->uri_auth = NULL; /* we must detach from the default config */
2995
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002996 if (!*args[1]) {
2997 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002998 } else if (!strcmp(args[1], "admin")) {
2999 struct stats_admin_rule *rule;
3000
3001 if (curproxy == &defproxy) {
3002 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
3006
3007 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3008 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3009 err_code |= ERR_ALERT | ERR_ABORT;
3010 goto out;
3011 }
3012
3013 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3014 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3015 file, linenum, args[0], args[1]);
3016 err_code |= ERR_ALERT | ERR_FATAL;
3017 goto out;
3018 }
3019 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3020 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3021 file, linenum, args[0], args[1]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
3026 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3027
3028 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3029 rule->cond = cond;
3030 LIST_INIT(&rule->list);
3031 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 } else if (!strcmp(args[1], "uri")) {
3033 if (*(args[2]) == 0) {
3034 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3038 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_ABORT;
3040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 }
3042 } else if (!strcmp(args[1], "realm")) {
3043 if (*(args[2]) == 0) {
3044 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3048 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_ABORT;
3050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003052 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003053 unsigned interval;
3054
3055 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3056 if (err) {
3057 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3058 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003061 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3062 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_ABORT;
3064 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003065 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003066 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
3067 struct req_acl_rule *req_acl;
3068
3069 if (curproxy == &defproxy) {
3070 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074
3075 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3076 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3077 err_code |= ERR_ALERT | ERR_ABORT;
3078 goto out;
3079 }
3080
3081 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
3082 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
3083 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3084 file, linenum, args[0]);
3085 err_code |= ERR_WARN;
3086 }
3087
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003088 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003089
3090 if (!req_acl) {
3091 err_code |= ERR_ALERT | ERR_ABORT;
3092 goto out;
3093 }
3094
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003095 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003096 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
3097
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 } else if (!strcmp(args[1], "auth")) {
3099 if (*(args[2]) == 0) {
3100 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3104 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_ABORT;
3106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 }
3108 } else if (!strcmp(args[1], "scope")) {
3109 if (*(args[2]) == 0) {
3110 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3114 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_ABORT;
3116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 }
3118 } else if (!strcmp(args[1], "enable")) {
3119 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3120 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003121 err_code |= ERR_ALERT | ERR_ABORT;
3122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003124 } else if (!strcmp(args[1], "hide-version")) {
3125 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_ABORT;
3128 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003129 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003130 } else if (!strcmp(args[1], "show-legends")) {
3131 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3132 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3133 err_code |= ERR_ALERT | ERR_ABORT;
3134 goto out;
3135 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003136 } else if (!strcmp(args[1], "show-node")) {
3137
3138 if (*args[2]) {
3139 int i;
3140 char c;
3141
3142 for (i=0; args[2][i]; i++) {
3143 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003144 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3145 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003146 break;
3147 }
3148
3149 if (!i || args[2][i]) {
3150 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3151 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3152 file, linenum, args[0], args[1]);
3153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
3155 }
3156 }
3157
3158 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3159 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3160 err_code |= ERR_ALERT | ERR_ABORT;
3161 goto out;
3162 }
3163 } else if (!strcmp(args[1], "show-desc")) {
3164 char *desc = NULL;
3165
3166 if (*args[2]) {
3167 int i, len=0;
3168 char *d;
3169
3170 for(i=2; *args[i]; i++)
3171 len += strlen(args[i])+1;
3172
3173 desc = d = (char *)calloc(1, len);
3174
3175 d += sprintf(d, "%s", args[2]);
3176 for(i=3; *args[i]; i++)
3177 d += sprintf(d, " %s", args[i]);
3178 }
3179
3180 if (!*args[2] && !global.desc)
3181 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3182 file, linenum, args[1]);
3183 else {
3184 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3185 free(desc);
3186 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3187 err_code |= ERR_ALERT | ERR_ABORT;
3188 goto out;
3189 }
3190 free(desc);
3191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003193stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003194 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003195 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 }
3199 }
3200 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003201 int optnum;
3202
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003203 if (*(args[1]) == '\0') {
3204 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003209
3210 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3211 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003212 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3213 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3214 file, linenum, cfg_opts[optnum].name);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
Willy Tarreau93893792009-07-23 13:19:11 +02003218 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3219 err_code |= ERR_WARN;
3220 goto out;
3221 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003222
Willy Tarreau3842f002009-06-14 11:39:52 +02003223 curproxy->no_options &= ~cfg_opts[optnum].val;
3224 curproxy->options &= ~cfg_opts[optnum].val;
3225
3226 switch (kwm) {
3227 case KWM_STD:
3228 curproxy->options |= cfg_opts[optnum].val;
3229 break;
3230 case KWM_NO:
3231 curproxy->no_options |= cfg_opts[optnum].val;
3232 break;
3233 case KWM_DEF: /* already cleared */
3234 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003235 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003236
Willy Tarreau93893792009-07-23 13:19:11 +02003237 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003238 }
3239 }
3240
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003241 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3242 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003243 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3244 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3245 file, linenum, cfg_opts2[optnum].name);
3246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
3248 }
Willy Tarreau93893792009-07-23 13:19:11 +02003249 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3250 err_code |= ERR_WARN;
3251 goto out;
3252 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003253
Willy Tarreau3842f002009-06-14 11:39:52 +02003254 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3255 curproxy->options2 &= ~cfg_opts2[optnum].val;
3256
3257 switch (kwm) {
3258 case KWM_STD:
3259 curproxy->options2 |= cfg_opts2[optnum].val;
3260 break;
3261 case KWM_NO:
3262 curproxy->no_options2 |= cfg_opts2[optnum].val;
3263 break;
3264 case KWM_DEF: /* already cleared */
3265 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003266 }
Willy Tarreau93893792009-07-23 13:19:11 +02003267 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003268 }
3269 }
3270
Willy Tarreau3842f002009-06-14 11:39:52 +02003271 if (kwm != KWM_STD) {
3272 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003273 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003276 }
3277
Emeric Brun3a058f32009-06-30 18:26:00 +02003278 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003280 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003282 if (*(args[2]) != '\0') {
3283 if (!strcmp(args[2], "clf")) {
3284 curproxy->options2 |= PR_O2_CLFLOG;
3285 } else {
3286 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003289 }
3290 }
3291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 else if (!strcmp(args[1], "tcplog"))
3293 /* generate a detailed TCP log */
3294 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 else if (!strcmp(args[1], "tcpka")) {
3296 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003297 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003299
3300 if (curproxy->cap & PR_CAP_FE)
3301 curproxy->options |= PR_O_TCP_CLI_KA;
3302 if (curproxy->cap & PR_CAP_BE)
3303 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
3305 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003306 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_WARN;
3308
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003310 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003311 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003312 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003313 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003314 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003315 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003316 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 if (!*args[2]) { /* no argument */
3318 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3319 curproxy->check_len = strlen(DEF_CHECK_REQ);
3320 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003321 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 curproxy->check_req = (char *)malloc(reqlen);
3323 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003324 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003326 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 if (*args[4])
3328 reqlen += strlen(args[4]);
3329 else
3330 reqlen += strlen("HTTP/1.0");
3331
3332 curproxy->check_req = (char *)malloc(reqlen);
3333 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003334 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003336 }
3337 else if (!strcmp(args[1], "ssl-hello-chk")) {
3338 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003339 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003340 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003341
Willy Tarreaua534fea2008-08-03 12:19:50 +02003342 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003343 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003344 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003345 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003346 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003347 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003348 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 }
Willy Tarreau23677902007-05-08 23:50:35 +02003350 else if (!strcmp(args[1], "smtpchk")) {
3351 /* use SMTP request to check servers' health */
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 Tarreau23677902007-05-08 23:50:35 +02003354 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003355 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003356 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003357 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003358 curproxy->options |= PR_O_SMTP_CHK;
3359
3360 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3361 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3362 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3363 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3364 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3365 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3366 curproxy->check_req = (char *)malloc(reqlen);
3367 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3368 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3369 } else {
3370 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3371 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3372 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3373 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3374 }
3375 }
3376 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003377 else if (!strcmp(args[1], "mysql-check")) {
3378 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003379 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3380 err_code |= ERR_WARN;
3381
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003382 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003383 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003384 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003385 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003386 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003387 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003388 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003389
3390 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3391 * const char mysql40_client_auth_pkt[] = {
3392 * "\x0e\x00\x00" // packet length
3393 * "\x01" // packet number
3394 * "\x00\x00" // client capabilities
3395 * "\x00\x00\x01" // max packet
3396 * "haproxy\x00" // username (null terminated string)
3397 * "\x00" // filler (always 0x00)
3398 * "\x01\x00\x00" // packet length
3399 * "\x00" // packet number
3400 * "\x01" // COM_QUIT command
3401 * };
3402 */
3403
3404 if (*(args[2])) {
3405 int cur_arg = 2;
3406
3407 while (*(args[cur_arg])) {
3408 if (strcmp(args[cur_arg], "user") == 0) {
3409 char *mysqluser;
3410 int packetlen, reqlen, userlen;
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 mysqluser = args[cur_arg + 1];
3420 userlen = strlen(mysqluser);
3421 packetlen = userlen + 7;
3422 reqlen = packetlen + 9;
3423
3424 free(curproxy->check_req);
3425 curproxy->check_req = (char *)calloc(1, reqlen);
3426 curproxy->check_len = reqlen;
3427
3428 snprintf(curproxy->check_req, 4, "%c%c%c",
3429 ((unsigned char) packetlen & 0xff),
3430 ((unsigned char) (packetlen >> 8) & 0xff),
3431 ((unsigned char) (packetlen >> 16) & 0xff));
3432
3433 curproxy->check_req[3] = 1;
3434 curproxy->check_req[8] = 1;
3435 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3436 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3437 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3438 cur_arg += 2;
3439 } else {
3440 /* unknown suboption - catchall */
3441 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3442 file, linenum, args[0], args[1]);
3443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
3445 }
3446 } /* end while loop */
3447 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003448 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003449 else if (!strcmp(args[1], "ldap-check")) {
3450 /* use LDAP request to check servers' health */
3451 free(curproxy->check_req);
3452 curproxy->check_req = NULL;
3453 curproxy->options &= ~PR_O_HTTP_CHK;
3454 curproxy->options &= ~PR_O_SMTP_CHK;
3455 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3456 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3457 curproxy->options2 |= PR_O2_LDAP_CHK;
3458
3459 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3460 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3461 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3462 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003463 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003464 int cur_arg;
3465
3466 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3467 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003468 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003469
3470 curproxy->options |= PR_O_FWDFOR;
3471
3472 free(curproxy->fwdfor_hdr_name);
3473 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3474 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3475
3476 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3477 cur_arg = 2;
3478 while (*(args[cur_arg])) {
3479 if (!strcmp(args[cur_arg], "except")) {
3480 /* suboption except - needs additional argument for it */
3481 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3482 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3483 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003486 }
3487 /* flush useless bits */
3488 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003489 cur_arg += 2;
3490 } else if (!strcmp(args[cur_arg], "header")) {
3491 /* suboption header - needs additional argument for it */
3492 if (*(args[cur_arg+1]) == 0) {
3493 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3494 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003495 err_code |= ERR_ALERT | ERR_FATAL;
3496 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003497 }
3498 free(curproxy->fwdfor_hdr_name);
3499 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3500 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3501 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003502 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003503 /* unknown suboption - catchall */
3504 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3505 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003508 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003509 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003510 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003511 else if (!strcmp(args[1], "originalto")) {
3512 int cur_arg;
3513
3514 /* insert x-original-to field, but not for the IP address listed as an except.
3515 * set default options (ie: bitfield, header name, etc)
3516 */
3517
3518 curproxy->options |= PR_O_ORGTO;
3519
3520 free(curproxy->orgto_hdr_name);
3521 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3522 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3523
3524 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3525 cur_arg = 2;
3526 while (*(args[cur_arg])) {
3527 if (!strcmp(args[cur_arg], "except")) {
3528 /* suboption except - needs additional argument for it */
3529 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3530 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3531 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003534 }
3535 /* flush useless bits */
3536 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3537 cur_arg += 2;
3538 } else if (!strcmp(args[cur_arg], "header")) {
3539 /* suboption header - needs additional argument for it */
3540 if (*(args[cur_arg+1]) == 0) {
3541 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3542 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003545 }
3546 free(curproxy->orgto_hdr_name);
3547 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3548 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3549 cur_arg += 2;
3550 } else {
3551 /* unknown suboption - catchall */
3552 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3553 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003554 err_code |= ERR_ALERT | ERR_FATAL;
3555 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003556 }
3557 } /* end while loop */
3558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 else {
3560 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003563 }
Willy Tarreau93893792009-07-23 13:19:11 +02003564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003566 else if (!strcmp(args[0], "default_backend")) {
3567 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003569
3570 if (*(args[1]) == 0) {
3571 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003574 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003575 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003576 curproxy->defbe.name = strdup(args[1]);
3577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003579 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003581
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003582 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3583 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 /* enable reconnections to dispatch */
3586 curproxy->options |= PR_O_REDISP;
3587 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003588 else if (!strcmp(args[0], "http-check")) {
3589 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003591
3592 if (strcmp(args[1], "disable-on-404") == 0) {
3593 /* enable a graceful server shutdown on an HTTP 404 response */
3594 curproxy->options |= PR_O_DISABLE404;
3595 }
Willy Tarreauef781042010-01-27 11:53:01 +01003596 else if (strcmp(args[1], "send-state") == 0) {
3597 /* enable emission of the apparent state of a server in HTTP checks */
3598 curproxy->options2 |= PR_O2_CHK_SNDST;
3599 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003600 else if (strcmp(args[1], "expect") == 0) {
3601 const char *ptr_arg;
3602 int cur_arg;
3603
3604 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3605 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
3608 }
3609
3610 cur_arg = 2;
3611 /* consider exclamation marks, sole or at the beginning of a word */
3612 while (*(ptr_arg = args[cur_arg])) {
3613 while (*ptr_arg == '!') {
3614 curproxy->options2 ^= PR_O2_EXP_INV;
3615 ptr_arg++;
3616 }
3617 if (*ptr_arg)
3618 break;
3619 cur_arg++;
3620 }
3621 /* now ptr_arg points to the beginning of a word past any possible
3622 * exclamation mark, and cur_arg is the argument which holds this word.
3623 */
3624 if (strcmp(ptr_arg, "status") == 0) {
3625 if (!*(args[cur_arg + 1])) {
3626 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3627 file, linenum, args[0], args[1], ptr_arg);
3628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
3630 }
3631 curproxy->options2 |= PR_O2_EXP_STS;
3632 curproxy->expect_str = strdup(args[cur_arg + 1]);
3633 }
3634 else if (strcmp(ptr_arg, "string") == 0) {
3635 if (!*(args[cur_arg + 1])) {
3636 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3637 file, linenum, args[0], args[1], ptr_arg);
3638 err_code |= ERR_ALERT | ERR_FATAL;
3639 goto out;
3640 }
3641 curproxy->options2 |= PR_O2_EXP_STR;
3642 curproxy->expect_str = strdup(args[cur_arg + 1]);
3643 }
3644 else if (strcmp(ptr_arg, "rstatus") == 0) {
3645 if (!*(args[cur_arg + 1])) {
3646 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3647 file, linenum, args[0], args[1], ptr_arg);
3648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
3650 }
3651 curproxy->options2 |= PR_O2_EXP_RSTS;
3652 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3653 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3654 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3655 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
3658 }
3659 }
3660 else if (strcmp(ptr_arg, "rstring") == 0) {
3661 if (!*(args[cur_arg + 1])) {
3662 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3663 file, linenum, args[0], args[1], ptr_arg);
3664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
3666 }
3667 curproxy->options2 |= PR_O2_EXP_RSTR;
3668 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3669 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3670 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3671 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3672 err_code |= ERR_ALERT | ERR_FATAL;
3673 goto out;
3674 }
3675 }
3676 else {
3677 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3678 file, linenum, args[0], args[1], ptr_arg);
3679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
3681 }
3682 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003683 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003684 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003687 }
3688 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003689 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003690 if (curproxy == &defproxy) {
3691 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003694 }
3695
Willy Tarreaub80c2302007-11-30 20:51:32 +01003696 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003697 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003698
3699 if (strcmp(args[1], "fail") == 0) {
3700 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003701 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003702 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3703 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003706 }
3707
Willy Tarreauef6494c2010-01-28 17:12:36 +01003708 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003709 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3710 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003713 }
3714 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3715 }
3716 else {
3717 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003720 }
3721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722#ifdef TPROXY
3723 else if (!strcmp(args[0], "transparent")) {
3724 /* enable transparent proxy connections */
3725 curproxy->options |= PR_O_TRANSP;
3726 }
3727#endif
3728 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003729 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003730 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003731
Willy Tarreaubaaee002006-06-26 02:48:02 +02003732 if (*(args[1]) == 0) {
3733 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 }
3737 curproxy->maxconn = atol(args[1]);
3738 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003739 else if (!strcmp(args[0], "backlog")) { /* backlog */
3740 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003742
3743 if (*(args[1]) == 0) {
3744 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003747 }
3748 curproxy->backlog = atol(args[1]);
3749 }
Willy Tarreau86034312006-12-29 00:10:33 +01003750 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003751 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003753
Willy Tarreau86034312006-12-29 00:10:33 +01003754 if (*(args[1]) == 0) {
3755 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003758 }
3759 curproxy->fullconn = atol(args[1]);
3760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003761 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3762 if (*(args[1]) == 0) {
3763 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003766 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003767 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3768 if (err) {
3769 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3770 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003773 }
3774 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 }
3776 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003777 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 if (curproxy == &defproxy) {
3779 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003782 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003783 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003785
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 if (strchr(args[1], ':') == NULL) {
3787 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003791 sk = str2sa(args[1]);
3792 if (!sk) {
3793 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
3796 }
3797 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 }
3799 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003800 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003801 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003802
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003803 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003804 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3805 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003810 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3811 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3812 err_code |= ERR_WARN;
3813
3814 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3815 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3816 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3817 }
3818 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3819 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3820 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3821 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003822 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3823 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3824 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3825 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003826 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003827 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830 }
3831 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003832 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003834 char *rport, *raddr;
3835 short realport = 0;
3836 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003838 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003839 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003843 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845
3846 if (!*args[2]) {
3847 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3848 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003852
3853 err = invalid_char(args[1]);
3854 if (err) {
3855 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3856 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003859 }
3860
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003861 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003862 struct sockaddr_in *sk;
3863
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003864 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3865 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3866 err_code |= ERR_ALERT | ERR_ABORT;
3867 goto out;
3868 }
3869
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003870 /* the servers are linked backwards first */
3871 newsrv->next = curproxy->srv;
3872 curproxy->srv = newsrv;
3873 newsrv->proxy = curproxy;
3874 newsrv->conf.file = file;
3875 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003877 LIST_INIT(&newsrv->pendconns);
3878 do_check = 0;
3879 newsrv->state = SRV_RUNNING; /* early server setup */
3880 newsrv->last_change = now.tv_sec;
3881 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003883 /* several ways to check the port component :
3884 * - IP => port=+0, relative
3885 * - IP: => port=+0, relative
3886 * - IP:N => port=N, absolute
3887 * - IP:+N => port=+N, relative
3888 * - IP:-N => port=-N, relative
3889 */
3890 raddr = strdup(args[2]);
3891 rport = strchr(raddr, ':');
3892 if (rport) {
3893 *rport++ = 0;
3894 realport = atol(rport);
3895 if (!isdigit((unsigned char)*rport))
3896 newsrv->state |= SRV_MAPPORTS;
3897 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003899
Willy Tarreaud5191e72010-02-09 20:50:45 +01003900 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003901 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003902 if (!sk) {
3903 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
3906 }
3907 newsrv->addr = *sk;
3908 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003909
3910 newsrv->check_port = curproxy->defsrv.check_port;
3911 newsrv->inter = curproxy->defsrv.inter;
3912 newsrv->fastinter = curproxy->defsrv.fastinter;
3913 newsrv->downinter = curproxy->defsrv.downinter;
3914 newsrv->rise = curproxy->defsrv.rise;
3915 newsrv->fall = curproxy->defsrv.fall;
3916 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3917 newsrv->minconn = curproxy->defsrv.minconn;
3918 newsrv->maxconn = curproxy->defsrv.maxconn;
3919 newsrv->slowstart = curproxy->defsrv.slowstart;
3920 newsrv->onerror = curproxy->defsrv.onerror;
3921 newsrv->consecutive_errors_limit
3922 = curproxy->defsrv.consecutive_errors_limit;
3923 newsrv->uweight = newsrv->iweight
3924 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003926 newsrv->curfd = -1; /* no health-check in progress */
3927 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003929 cur_arg = 3;
3930 } else {
3931 newsrv = &curproxy->defsrv;
3932 cur_arg = 1;
3933 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003934
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003936 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003937 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003938
3939 if (!*args[cur_arg + 1]) {
3940 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3941 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003944 }
3945
3946 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003947 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003948
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003949 if (newsrv->puid <= 0) {
3950 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003951 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003954 }
3955
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003956 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3957 if (node) {
3958 struct server *target = container_of(node, struct server, conf.id);
3959 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3960 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
3963 }
3964 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003965 cur_arg += 2;
3966 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003967 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 newsrv->cookie = strdup(args[cur_arg + 1]);
3969 newsrv->cklen = strlen(args[cur_arg + 1]);
3970 cur_arg += 2;
3971 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003972 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003973 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3974 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3975 cur_arg += 2;
3976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003978 if (!*args[cur_arg + 1]) {
3979 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3980 file, linenum, args[cur_arg]);
3981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
3983 }
3984
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003986 if (newsrv->rise <= 0) {
3987 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3988 file, linenum, args[cur_arg]);
3989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
3991 }
3992
Willy Tarreau96839092010-03-29 10:02:24 +02003993 if (newsrv->health)
3994 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995 cur_arg += 2;
3996 }
3997 else if (!strcmp(args[cur_arg], "fall")) {
3998 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003999
4000 if (!*args[cur_arg + 1]) {
4001 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4002 file, linenum, args[cur_arg]);
4003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
4005 }
4006
4007 if (newsrv->fall <= 0) {
4008 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4009 file, linenum, args[cur_arg]);
4010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
4012 }
4013
Willy Tarreaubaaee002006-06-26 02:48:02 +02004014 cur_arg += 2;
4015 }
4016 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004017 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4018 if (err) {
4019 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4020 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004023 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004024 if (val <= 0) {
4025 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4026 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004029 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004030 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 cur_arg += 2;
4032 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004033 else if (!strcmp(args[cur_arg], "fastinter")) {
4034 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4035 if (err) {
4036 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4037 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004040 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004041 if (val <= 0) {
4042 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4043 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004046 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004047 newsrv->fastinter = val;
4048 cur_arg += 2;
4049 }
4050 else if (!strcmp(args[cur_arg], "downinter")) {
4051 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4052 if (err) {
4053 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4054 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004057 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004058 if (val <= 0) {
4059 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4060 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004063 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004064 newsrv->downinter = val;
4065 cur_arg += 2;
4066 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004067 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004068 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4069 if (!sk) {
4070 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
4074 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004075 cur_arg += 2;
4076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004077 else if (!strcmp(args[cur_arg], "port")) {
4078 newsrv->check_port = atol(args[cur_arg + 1]);
4079 cur_arg += 2;
4080 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004081 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004082 newsrv->state |= SRV_BACKUP;
4083 cur_arg ++;
4084 }
4085 else if (!strcmp(args[cur_arg], "weight")) {
4086 int w;
4087 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004088 if (w < 0 || w > 256) {
4089 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004090 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004093 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004094 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004095 cur_arg += 2;
4096 }
4097 else if (!strcmp(args[cur_arg], "minconn")) {
4098 newsrv->minconn = atol(args[cur_arg + 1]);
4099 cur_arg += 2;
4100 }
4101 else if (!strcmp(args[cur_arg], "maxconn")) {
4102 newsrv->maxconn = atol(args[cur_arg + 1]);
4103 cur_arg += 2;
4104 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004105 else if (!strcmp(args[cur_arg], "maxqueue")) {
4106 newsrv->maxqueue = atol(args[cur_arg + 1]);
4107 cur_arg += 2;
4108 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004109 else if (!strcmp(args[cur_arg], "slowstart")) {
4110 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004111 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004112 if (err) {
4113 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4114 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004117 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004118 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004119 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4120 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004123 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004124 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004125 cur_arg += 2;
4126 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004127 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004128
4129 if (!*args[cur_arg + 1]) {
4130 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4131 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004134 }
4135
4136 newsrv->trackit = strdup(args[cur_arg + 1]);
4137
4138 cur_arg += 2;
4139 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004140 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004141 global.maxsock++;
4142 do_check = 1;
4143 cur_arg += 1;
4144 }
Willy Tarreau96839092010-03-29 10:02:24 +02004145 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4146 newsrv->state |= SRV_MAINTAIN;
4147 newsrv->state &= ~SRV_RUNNING;
4148 newsrv->health = 0;
4149 cur_arg += 1;
4150 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004151 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004152 if (!strcmp(args[cur_arg + 1], "none"))
4153 newsrv->observe = HANA_OBS_NONE;
4154 else if (!strcmp(args[cur_arg + 1], "layer4"))
4155 newsrv->observe = HANA_OBS_LAYER4;
4156 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4157 if (curproxy->mode != PR_MODE_HTTP) {
4158 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4159 file, linenum, args[cur_arg + 1]);
4160 err_code |= ERR_ALERT;
4161 }
4162 newsrv->observe = HANA_OBS_LAYER7;
4163 }
4164 else {
4165 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004166 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004167 file, linenum, args[cur_arg], args[cur_arg + 1]);
4168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
4170 }
4171
4172 cur_arg += 2;
4173 }
4174 else if (!strcmp(args[cur_arg], "on-error")) {
4175 if (!strcmp(args[cur_arg + 1], "fastinter"))
4176 newsrv->onerror = HANA_ONERR_FASTINTER;
4177 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4178 newsrv->onerror = HANA_ONERR_FAILCHK;
4179 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4180 newsrv->onerror = HANA_ONERR_SUDDTH;
4181 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4182 newsrv->onerror = HANA_ONERR_MARKDWN;
4183 else {
4184 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004185 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004186 file, linenum, args[cur_arg], args[cur_arg + 1]);
4187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
4189 }
4190
4191 cur_arg += 2;
4192 }
4193 else if (!strcmp(args[cur_arg], "error-limit")) {
4194 if (!*args[cur_arg + 1]) {
4195 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4196 file, linenum, args[cur_arg]);
4197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
4199 }
4200
4201 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4202
4203 if (newsrv->consecutive_errors_limit <= 0) {
4204 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4205 file, linenum, args[cur_arg]);
4206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
4208 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004209 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004210 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004211 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004212 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004213 struct sockaddr_in *sk;
4214
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004216#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004217 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004218 file, linenum, "source", "usesrc");
4219#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004220 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004221 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004222#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 }
4226 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004227 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4228 if (!sk) {
4229 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
4232 }
4233 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004234
4235 if (port_low != port_high) {
4236 int i;
4237 if (port_low <= 0 || port_low > 65535 ||
4238 port_high <= 0 || port_high > 65535 ||
4239 port_low > port_high) {
4240 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4241 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004244 }
4245 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4246 for (i = 0; i < newsrv->sport_range->size; i++)
4247 newsrv->sport_range->ports[i] = port_low + i;
4248 }
4249
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004251 while (*(args[cur_arg])) {
4252 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004253#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4254#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004255 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4256 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4257 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004258 err_code |= ERR_ALERT | ERR_FATAL;
4259 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004260 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004261#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004262 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004263 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004264 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004267 }
4268 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004269 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004270 newsrv->state |= SRV_TPROXY_CLI;
4271 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004272 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004273 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004274 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4275 char *name, *end;
4276
4277 name = args[cur_arg+1] + 7;
4278 while (isspace(*name))
4279 name++;
4280
4281 end = name;
4282 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4283 end++;
4284
4285 newsrv->state &= ~SRV_TPROXY_MASK;
4286 newsrv->state |= SRV_TPROXY_DYN;
4287 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4288 newsrv->bind_hdr_len = end - name;
4289 memcpy(newsrv->bind_hdr_name, name, end - name);
4290 newsrv->bind_hdr_name[end-name] = '\0';
4291 newsrv->bind_hdr_occ = -1;
4292
4293 /* now look for an occurrence number */
4294 while (isspace(*end))
4295 end++;
4296 if (*end == ',') {
4297 end++;
4298 name = end;
4299 if (*end == '-')
4300 end++;
4301 while (isdigit(*end))
4302 end++;
4303 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4304 }
4305
4306 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4307 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4308 " occurrences values smaller than %d.\n",
4309 file, linenum, MAX_HDR_HISTORY);
4310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
4312 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004313 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004314 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4315 if (!sk) {
4316 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4317 err_code |= ERR_ALERT | ERR_FATAL;
4318 goto out;
4319 }
4320 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004321 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004322 }
4323 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004324#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004325 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004326#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004327 cur_arg += 2;
4328 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004329#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004330 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004331 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004334#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4335 } /* "usesrc" */
4336
4337 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4338#ifdef SO_BINDTODEVICE
4339 if (!*args[cur_arg + 1]) {
4340 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4341 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004344 }
4345 if (newsrv->iface_name)
4346 free(newsrv->iface_name);
4347
4348 newsrv->iface_name = strdup(args[cur_arg + 1]);
4349 newsrv->iface_len = strlen(newsrv->iface_name);
4350 global.last_checks |= LSTCHK_NETADM;
4351#else
4352 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4353 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004356#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004357 cur_arg += 2;
4358 continue;
4359 }
4360 /* this keyword in not an option of "source" */
4361 break;
4362 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004364 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004365 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4366 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004371 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004372 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 +01004373 file, linenum, newsrv->id);
4374 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004375 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 +01004376 file, linenum);
4377
Willy Tarreau93893792009-07-23 13:19:11 +02004378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004380 }
4381 }
4382
4383 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004384 if (newsrv->trackit) {
4385 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4386 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004389 }
4390
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004391 if (!newsrv->check_port && newsrv->check_addr.sin_port)
4392 newsrv->check_port = newsrv->check_addr.sin_port;
4393
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4395 newsrv->check_port = realport; /* by default */
4396 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004397 /* not yet valid, because no port was set on
4398 * the server either. We'll check if we have
4399 * a known port on the first listener.
4400 */
4401 struct listener *l;
4402 l = curproxy->listen;
4403 if (l) {
4404 int port;
4405 port = (l->addr.ss_family == AF_INET6)
4406 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4407 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4408 newsrv->check_port = port;
4409 }
4410 }
4411 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4413 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004417
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004418 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004419 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004420 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4421 err_code |= ERR_ALERT | ERR_ABORT;
4422 goto out;
4423 }
4424
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004425 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004426 newsrv->state |= SRV_CHECKED;
4427 }
4428
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004429 if (!defsrv) {
4430 if (newsrv->state & SRV_BACKUP)
4431 curproxy->srv_bck++;
4432 else
4433 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004434
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004435 newsrv->prev_state = newsrv->state;
4436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 }
4438 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004439 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004440 int facility;
4441
4442 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4443 curproxy->logfac1 = global.logfac1;
4444 curproxy->logsrv1 = global.logsrv1;
4445 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004446 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 curproxy->logfac2 = global.logfac2;
4448 curproxy->logsrv2 = global.logsrv2;
4449 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004450 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 }
4452 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004453 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454
4455 facility = get_log_facility(args[2]);
4456 if (facility < 0) {
4457 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4458 exit(1);
4459 }
4460
4461 level = 7; /* max syslog level = debug */
4462 if (*(args[3])) {
4463 level = get_log_level(args[3]);
4464 if (level < 0) {
4465 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4466 exit(1);
4467 }
4468 }
4469
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004470 minlvl = 0; /* limit syslog level to this level (emerg) */
4471 if (*(args[4])) {
4472 minlvl = get_log_level(args[4]);
4473 if (level < 0) {
4474 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4475 exit(1);
4476 }
4477 }
4478
Robert Tsai81ae1952007-12-05 10:47:29 +01004479 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004480 struct sockaddr_un *sk = str2sun(args[1]);
4481 if (!sk) {
4482 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4483 args[1], (int)sizeof(sk->sun_path) - 1);
4484 err_code |= ERR_ALERT | ERR_FATAL;
4485 goto out;
4486 }
4487 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004488 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004489 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004490 struct sockaddr_in *sk = str2sa(args[1]);
4491 if (!sk) {
4492 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
4495 }
4496 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004497 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004498 if (!logsrv.u.in.sin_port) {
4499 logsrv.u.in.sin_port =
4500 htons(SYSLOG_PORT);
4501 }
4502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503
4504 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004505 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 curproxy->logfac1 = facility;
4507 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004508 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 }
4510 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004511 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 curproxy->logfac2 = facility;
4513 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004514 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 }
4516 else {
4517 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004518 err_code |= ERR_ALERT | ERR_FATAL;
4519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 }
4521 }
4522 else {
4523 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4524 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004527 }
4528 }
4529 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004530 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004531 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004532
Willy Tarreau977b8e42006-12-29 14:19:17 +01004533 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004534 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004535
Willy Tarreaubaaee002006-06-26 02:48:02 +02004536 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004537 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4538 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004539 err_code |= ERR_ALERT | ERR_FATAL;
4540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004542
4543 /* we must first clear any optional default setting */
4544 curproxy->options &= ~PR_O_TPXY_MASK;
4545 free(curproxy->iface_name);
4546 curproxy->iface_name = NULL;
4547 curproxy->iface_len = 0;
4548
Willy Tarreaud5191e72010-02-09 20:50:45 +01004549 sk = str2sa(args[1]);
4550 if (!sk) {
4551 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
4555 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004556 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004557
4558 cur_arg = 2;
4559 while (*(args[cur_arg])) {
4560 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004561#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4562#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004563 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4564 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4565 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004568 }
4569#endif
4570 if (!*args[cur_arg + 1]) {
4571 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4572 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004575 }
4576
4577 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004578 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004579 curproxy->options |= PR_O_TPXY_CLI;
4580 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004581 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004582 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004583 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4584 char *name, *end;
4585
4586 name = args[cur_arg+1] + 7;
4587 while (isspace(*name))
4588 name++;
4589
4590 end = name;
4591 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4592 end++;
4593
4594 curproxy->options &= ~PR_O_TPXY_MASK;
4595 curproxy->options |= PR_O_TPXY_DYN;
4596 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4597 curproxy->bind_hdr_len = end - name;
4598 memcpy(curproxy->bind_hdr_name, name, end - name);
4599 curproxy->bind_hdr_name[end-name] = '\0';
4600 curproxy->bind_hdr_occ = -1;
4601
4602 /* now look for an occurrence number */
4603 while (isspace(*end))
4604 end++;
4605 if (*end == ',') {
4606 end++;
4607 name = end;
4608 if (*end == '-')
4609 end++;
4610 while (isdigit(*end))
4611 end++;
4612 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4613 }
4614
4615 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4616 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4617 " occurrences values smaller than %d.\n",
4618 file, linenum, MAX_HDR_HISTORY);
4619 err_code |= ERR_ALERT | ERR_FATAL;
4620 goto out;
4621 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004622 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004623 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4624 if (!sk) {
4625 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4626 err_code |= ERR_ALERT | ERR_FATAL;
4627 goto out;
4628 }
4629 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004630 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004631 }
4632 global.last_checks |= LSTCHK_NETADM;
4633#if !defined(CONFIG_HAP_LINUX_TPROXY)
4634 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004635#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004636#else /* no TPROXY support */
4637 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004638 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004641#endif
4642 cur_arg += 2;
4643 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004644 }
4645
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004646 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4647#ifdef SO_BINDTODEVICE
4648 if (!*args[cur_arg + 1]) {
4649 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4650 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004651 err_code |= ERR_ALERT | ERR_FATAL;
4652 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004653 }
4654 if (curproxy->iface_name)
4655 free(curproxy->iface_name);
4656
4657 curproxy->iface_name = strdup(args[cur_arg + 1]);
4658 curproxy->iface_len = strlen(curproxy->iface_name);
4659 global.last_checks |= LSTCHK_NETADM;
4660#else
4661 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4662 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004665#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004666 cur_arg += 2;
4667 continue;
4668 }
4669 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4670 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004671 err_code |= ERR_ALERT | ERR_FATAL;
4672 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004673 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004674 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004675 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4676 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4677 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004680 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004681 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004682 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4684 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004685 err_code |= ERR_ALERT | ERR_FATAL;
4686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004688
4689 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4690 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004691 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004692 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 }
4695 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004696 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4697 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004698 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004699 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004701 }
4702 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004703 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4704 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004705 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004706 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 }
4709 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004710 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4711 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004712 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004713 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004715 }
4716 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004717 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4718 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004719 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004720 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004723 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004724 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4725 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004726 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004727 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004728 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004729 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004730 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004731 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4732 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004733 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004734 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004735 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004736 }
4737 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004738 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4739 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004740 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004741 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004742 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004743 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004745 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4747 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004751
4752 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4753 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004754 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004755 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
4758 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004759 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4760 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004761 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004762 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
4765 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004766 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4767 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004768 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004769 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 }
4772 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004773 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4774 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004775 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004776 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 }
4779 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004780 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4781 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004782 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004783 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004785 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004786 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004787 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4788 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004789 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004790 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004791 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004794 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004795
Willy Tarreaubaaee002006-06-26 02:48:02 +02004796 if (curproxy == &defproxy) {
4797 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004798 err_code |= ERR_ALERT | ERR_FATAL;
4799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004801 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804 if (*(args[1]) == 0) {
4805 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004806 err_code |= ERR_ALERT | ERR_FATAL;
4807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004808 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004809
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004810 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4811 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4812 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4813 file, linenum, args[0]);
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
4816 }
4817 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4818 }
4819 else if (*args[2]) {
4820 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4821 file, linenum, args[0], args[2]);
4822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
4824 }
4825
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004826 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004827 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004828 wl->s = strdup(args[1]);
4829 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004830 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 }
4832 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004833 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004834 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4835 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004839
Willy Tarreauade5ec42010-01-28 19:33:49 +01004840 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4841 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004842 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004843 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 }
4846 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004847 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4848 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004849 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004850 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 }
4853 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004854 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4855 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004856 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004857 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 }
4860 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004861 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4863 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004864 err_code |= ERR_ALERT | ERR_FATAL;
4865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 }
4867
Willy Tarreauade5ec42010-01-28 19:33:49 +01004868 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4869 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004870 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004871 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873 }
4874 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004875 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4876 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004877 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004878 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004880 }
4881 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004882 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4883 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004884 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004885 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887 }
4888 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004889 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004890
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891 if (curproxy == &defproxy) {
4892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004893 err_code |= ERR_ALERT | ERR_FATAL;
4894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004895 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004896 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004897 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 if (*(args[1]) == 0) {
4900 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 }
4904
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004905 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4906 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4907 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4908 file, linenum, args[0]);
4909 err_code |= ERR_ALERT | ERR_FATAL;
4910 goto out;
4911 }
4912 err_code |= warnif_cond_requires_req(cond, file, linenum);
4913 }
4914 else if (*args[2]) {
4915 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4916 file, linenum, args[0], args[2]);
4917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
4919 }
4920
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004921 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004922 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004923 wl->s = strdup(args[1]);
4924 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 }
4926 else if (!strcmp(args[0], "errorloc") ||
4927 !strcmp(args[0], "errorloc302") ||
4928 !strcmp(args[0], "errorloc303")) { /* error location */
4929 int errnum, errlen;
4930 char *err;
4931
Willy Tarreau977b8e42006-12-29 14:19:17 +01004932 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004933 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004934
Willy Tarreaubaaee002006-06-26 02:48:02 +02004935 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004936 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 }
4940
4941 errnum = atol(args[1]);
4942 if (!strcmp(args[0], "errorloc303")) {
4943 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4944 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4945 } else {
4946 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4947 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4948 }
4949
Willy Tarreau0f772532006-12-23 20:51:41 +01004950 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4951 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004952 chunk_destroy(&curproxy->errmsg[rc]);
4953 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004954 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004957
4958 if (rc >= HTTP_ERR_SIZE) {
4959 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4960 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 free(err);
4962 }
4963 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004964 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4965 int errnum, errlen, fd;
4966 char *err;
4967 struct stat stat;
4968
4969 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004970 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004971
4972 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004973 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004974 err_code |= ERR_ALERT | ERR_FATAL;
4975 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004976 }
4977
4978 fd = open(args[2], O_RDONLY);
4979 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4980 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4981 file, linenum, args[2], args[1]);
4982 if (fd >= 0)
4983 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004986 }
4987
Willy Tarreau27a674e2009-08-17 07:23:33 +02004988 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004989 errlen = stat.st_size;
4990 } else {
4991 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004992 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004993 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004994 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004995 }
4996
4997 err = malloc(errlen); /* malloc() must succeed during parsing */
4998 errnum = read(fd, err, errlen);
4999 if (errnum != errlen) {
5000 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5001 file, linenum, args[2], args[1]);
5002 close(fd);
5003 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005006 }
5007 close(fd);
5008
5009 errnum = atol(args[1]);
5010 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5011 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005012 chunk_destroy(&curproxy->errmsg[rc]);
5013 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005014 break;
5015 }
5016 }
5017
5018 if (rc >= HTTP_ERR_SIZE) {
5019 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5020 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005022 free(err);
5023 }
5024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005026 struct cfg_kw_list *kwl;
5027 int index;
5028
5029 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5030 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5031 if (kwl->kw[index].section != CFG_LISTEN)
5032 continue;
5033 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5034 /* prepare error message just in case */
5035 snprintf(trash, sizeof(trash),
5036 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005037 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5038 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005039 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005042 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005043 else if (rc > 0) {
5044 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005045 err_code |= ERR_WARN;
5046 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005047 }
Willy Tarreau93893792009-07-23 13:19:11 +02005048 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005049 }
5050 }
5051 }
5052
Willy Tarreau6daf3432008-01-22 16:44:08 +01005053 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 }
Willy Tarreau93893792009-07-23 13:19:11 +02005057 out:
5058 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059}
5060
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005061int
5062cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5063{
5064
5065 int err_code = 0;
5066 const char *err;
5067
5068 if (!strcmp(args[0], "userlist")) { /* new userlist */
5069 struct userlist *newul;
5070
5071 if (!*args[1]) {
5072 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5073 file, linenum, args[0]);
5074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
5076 }
5077
5078 err = invalid_char(args[1]);
5079 if (err) {
5080 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5081 file, linenum, *err, args[0], args[1]);
5082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
5084 }
5085
5086 for (newul = userlist; newul; newul = newul->next)
5087 if (!strcmp(newul->name, args[1])) {
5088 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5089 file, linenum, args[1]);
5090 err_code |= ERR_WARN;
5091 goto out;
5092 }
5093
5094 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5095 if (!newul) {
5096 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5097 err_code |= ERR_ALERT | ERR_ABORT;
5098 goto out;
5099 }
5100
5101 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5102 newul->name = strdup(args[1]);
5103
5104 if (!newul->groupusers | !newul->name) {
5105 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5106 err_code |= ERR_ALERT | ERR_ABORT;
5107 goto out;
5108 }
5109
5110 newul->next = userlist;
5111 userlist = newul;
5112
5113 } else if (!strcmp(args[0], "group")) { /* new group */
5114 int cur_arg, i;
5115 const char *err;
5116
5117 if (!*args[1]) {
5118 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5119 file, linenum, args[0]);
5120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
5122 }
5123
5124 err = invalid_char(args[1]);
5125 if (err) {
5126 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5127 file, linenum, *err, args[0], args[1]);
5128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
5130 }
5131
5132 for(i = 0; i < userlist->grpcnt; i++)
5133 if (!strcmp(userlist->groups[i], args[1])) {
5134 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5135 file, linenum, args[1], userlist->name);
5136 err_code |= ERR_ALERT;
5137 goto out;
5138 }
5139
5140 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5141 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5142 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
5145 }
5146
5147 cur_arg = 2;
5148
5149 while (*args[cur_arg]) {
5150 if (!strcmp(args[cur_arg], "users")) {
5151 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5152 cur_arg += 2;
5153 continue;
5154 } else {
5155 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5156 file, linenum, args[0]);
5157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
5159 }
5160 }
5161
5162 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5163 } else if (!strcmp(args[0], "user")) { /* new user */
5164 struct auth_users *newuser;
5165 int cur_arg;
5166
5167 if (!*args[1]) {
5168 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5169 file, linenum, args[0]);
5170 err_code |= ERR_ALERT | ERR_FATAL;
5171 goto out;
5172 }
5173
5174 for (newuser = userlist->users; newuser; newuser = newuser->next)
5175 if (!strcmp(newuser->user, args[1])) {
5176 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5177 file, linenum, args[1], userlist->name);
5178 err_code |= ERR_ALERT;
5179 goto out;
5180 }
5181
5182 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5183 if (!newuser) {
5184 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5185 err_code |= ERR_ALERT | ERR_ABORT;
5186 goto out;
5187 }
5188
5189 newuser->user = strdup(args[1]);
5190
5191 newuser->next = userlist->users;
5192 userlist->users = newuser;
5193
5194 cur_arg = 2;
5195
5196 while (*args[cur_arg]) {
5197 if (!strcmp(args[cur_arg], "password")) {
5198#ifndef CONFIG_HAP_CRYPT
5199 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5200 file, linenum);
5201 err_code |= ERR_ALERT;
5202#endif
5203 newuser->pass = strdup(args[cur_arg + 1]);
5204 cur_arg += 2;
5205 continue;
5206 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5207 newuser->pass = strdup(args[cur_arg + 1]);
5208 newuser->flags |= AU_O_INSECURE;
5209 cur_arg += 2;
5210 continue;
5211 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005212 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005213 cur_arg += 2;
5214 continue;
5215 } else {
5216 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5217 file, linenum, args[0]);
5218 err_code |= ERR_ALERT | ERR_FATAL;
5219 goto out;
5220 }
5221 }
5222 } else {
5223 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5224 err_code |= ERR_ALERT | ERR_FATAL;
5225 }
5226
5227out:
5228 return err_code;
5229}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230
5231/*
5232 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005233 * Returns the error code, 0 if OK, or any combination of :
5234 * - ERR_ABORT: must abort ASAP
5235 * - ERR_FATAL: we can continue parsing but not start the service
5236 * - ERR_WARN: a warning has been emitted
5237 * - ERR_ALERT: an alert has been emitted
5238 * Only the two first ones can stop processing, the two others are just
5239 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005241int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005243 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 FILE *f;
5245 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005246 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005247 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 if ((f=fopen(file,"r")) == NULL)
5250 return -1;
5251
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005252 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005253 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005254 char *end;
5255 char *args[MAX_LINE_ARGS + 1];
5256 char *line = thisline;
5257
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 linenum++;
5259
5260 end = line + strlen(line);
5261
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005262 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5263 /* Check if we reached the limit and the last char is not \n.
5264 * Watch out for the last line without the terminating '\n'!
5265 */
5266 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005267 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005268 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005269 }
5270
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005272 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 line++;
5274
5275 arg = 0;
5276 args[arg] = line;
5277
5278 while (*line && arg < MAX_LINE_ARGS) {
5279 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5280 * C equivalent value. Other combinations left unchanged (eg: \1).
5281 */
5282 if (*line == '\\') {
5283 int skip = 0;
5284 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5285 *line = line[1];
5286 skip = 1;
5287 }
5288 else if (line[1] == 'r') {
5289 *line = '\r';
5290 skip = 1;
5291 }
5292 else if (line[1] == 'n') {
5293 *line = '\n';
5294 skip = 1;
5295 }
5296 else if (line[1] == 't') {
5297 *line = '\t';
5298 skip = 1;
5299 }
5300 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005301 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 unsigned char hex1, hex2;
5303 hex1 = toupper(line[2]) - '0';
5304 hex2 = toupper(line[3]) - '0';
5305 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5306 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5307 *line = (hex1<<4) + hex2;
5308 skip = 3;
5309 }
5310 else {
5311 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005312 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 }
5314 }
5315 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005316 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 end -= skip;
5318 }
5319 line++;
5320 }
5321 else if (*line == '#' || *line == '\n' || *line == '\r') {
5322 /* end of string, end of loop */
5323 *line = 0;
5324 break;
5325 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005326 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005328 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005329 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 line++;
5331 args[++arg] = line;
5332 }
5333 else {
5334 line++;
5335 }
5336 }
5337
5338 /* empty line */
5339 if (!**args)
5340 continue;
5341
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005342 if (*line) {
5343 /* we had to stop due to too many args.
5344 * Let's terminate the string, print the offending part then cut the
5345 * last arg.
5346 */
5347 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5348 line++;
5349 *line = '\0';
5350
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005351 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005352 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005353 err_code |= ERR_ALERT | ERR_FATAL;
5354 args[arg] = line;
5355 }
5356
Willy Tarreau540abe42007-05-02 20:50:16 +02005357 /* zero out remaining args and ensure that at least one entry
5358 * is zeroed out.
5359 */
5360 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005361 args[arg] = line;
5362 }
5363
Willy Tarreau3842f002009-06-14 11:39:52 +02005364 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005365 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005366 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005367 for (arg=0; *args[arg+1]; arg++)
5368 args[arg] = args[arg+1]; // shift args after inversion
5369 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005370 else if (!strcmp(args[0], "default")) {
5371 kwm = KWM_DEF;
5372 for (arg=0; *args[arg+1]; arg++)
5373 args[arg] = args[arg+1]; // shift args after inversion
5374 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005375
Willy Tarreau3842f002009-06-14 11:39:52 +02005376 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5377 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005378 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005379 }
5380
Willy Tarreau977b8e42006-12-29 14:19:17 +01005381 if (!strcmp(args[0], "listen") ||
5382 !strcmp(args[0], "frontend") ||
5383 !strcmp(args[0], "backend") ||
5384 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005385 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005387 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005388 cursection = strdup(args[0]);
5389 }
5390 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005392 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005393 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005394 }
5395 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005396 confsect = CFG_USERLIST;
5397 free(cursection);
5398 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005399 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005400 else if (!strcmp(args[0], "peers")) {
5401 confsect = CFG_PEERS;
5402 free(cursection);
5403 cursection = strdup(args[0]);
5404 }
5405
Willy Tarreaubaaee002006-06-26 02:48:02 +02005406 /* else it's a section keyword */
5407
5408 switch (confsect) {
5409 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005410 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005411 break;
5412 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005413 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005414 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005415 case CFG_USERLIST:
5416 err_code |= cfg_parse_users(file, linenum, args, kwm);
5417 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005418 case CFG_PEERS:
5419 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5420 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005422 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005423 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005425
5426 if (err_code & ERR_ABORT)
5427 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005428 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005429 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005430 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005431 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005432 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005433}
5434
Willy Tarreaubb925012009-07-23 13:36:36 +02005435/*
5436 * Returns the error code, 0 if OK, or any combination of :
5437 * - ERR_ABORT: must abort ASAP
5438 * - ERR_FATAL: we can continue parsing but not start the service
5439 * - ERR_WARN: a warning has been emitted
5440 * - ERR_ALERT: an alert has been emitted
5441 * Only the two first ones can stop processing, the two others are just
5442 * indicators.
5443 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005444int check_config_validity()
5445{
5446 int cfgerr = 0;
5447 struct proxy *curproxy = NULL;
5448 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005449 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005450 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005451 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005452
5453 /*
5454 * Now, check for the integrity of all that we have collected.
5455 */
5456
5457 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005458 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005459
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005460 /* first, we will invert the proxy list order */
5461 curproxy = NULL;
5462 while (proxy) {
5463 struct proxy *next;
5464
5465 next = proxy->next;
5466 proxy->next = curproxy;
5467 curproxy = proxy;
5468 if (!next)
5469 break;
5470 proxy = next;
5471 }
5472
Willy Tarreaubaaee002006-06-26 02:48:02 +02005473 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005474 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005475 err_code |= ERR_ALERT | ERR_FATAL;
5476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477 }
5478
5479 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005480 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005481 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005482 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005483 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005484 unsigned int next_id;
5485
5486 if (!curproxy->uuid) {
5487 /* proxy ID not set, use automatic numbering with first
5488 * spare entry starting with next_pxid.
5489 */
5490 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5491 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5492 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005493 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005494 next_pxid++;
5495
Willy Tarreau55ea7572007-06-17 19:56:27 +02005496
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005498 /* ensure we don't keep listeners uselessly bound */
5499 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005500 curproxy = curproxy->next;
5501 continue;
5502 }
5503
Willy Tarreauff01a212009-03-15 13:46:16 +01005504 switch (curproxy->mode) {
5505 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005506 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005507 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005508 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5509 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005510 cfgerr++;
5511 }
5512
5513 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005514 Warning("config : servers will be ignored for %s '%s'.\n",
5515 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005516 break;
5517
5518 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005519 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005520 break;
5521
5522 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005523 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005524 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005525 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5526 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005527 cfgerr++;
5528 }
5529 break;
5530 }
5531
5532 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005533 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5534 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 cfgerr++;
5536 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005537
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005538 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005539 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005540 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005541 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5542 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005543 cfgerr++;
5544 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005546 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005547 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5548 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005549 cfgerr++;
5550 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005551#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005552 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005553 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5554 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005555 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005556 }
5557 }
5558 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
5559 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
5560 /* If no LB algo is set in a backend, and we're not in
5561 * transparent mode, dispatch mode nor proxy mode, we
5562 * want to use balance roundrobin by default.
5563 */
5564 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5565 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 }
5567 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005568
Willy Tarreau82936582007-11-30 15:20:09 +01005569 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5570 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005571 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5572 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005573 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005574 }
5575
Willy Tarreauef781042010-01-27 11:53:01 +01005576 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5577 curproxy->options &= ~PR_O2_CHK_SNDST;
5578 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5579 "send-state", proxy_type_str(curproxy), curproxy->id);
5580 err_code |= ERR_WARN;
5581 }
5582
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005583 /* if a default backend was specified, let's find it */
5584 if (curproxy->defbe.name) {
5585 struct proxy *target;
5586
Alex Williams96532db2009-11-01 21:27:13 -05005587 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005588 if (!target) {
5589 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5590 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005591 cfgerr++;
5592 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005593 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5594 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005595 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005596 } else {
5597 free(curproxy->defbe.name);
5598 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005599 /* we force the backend to be present on at least all of
5600 * the frontend's processes.
5601 */
5602 target->bind_proc = curproxy->bind_proc ?
5603 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 }
5605 }
5606
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005607 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005608 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5609 /* map jump target for ACT_SETBE in req_rep chain */
5610 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005611 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005612 struct proxy *target;
5613
Willy Tarreaua496b602006-12-17 23:15:24 +01005614 if (exp->action != ACT_SETBE)
5615 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005616
Alex Williams96532db2009-11-01 21:27:13 -05005617 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005618 if (!target) {
5619 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5620 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005621 cfgerr++;
5622 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005623 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5624 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005625 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005626 } else {
5627 free((void *)exp->replace);
5628 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005629 /* we force the backend to be present on at least all of
5630 * the frontend's processes.
5631 */
5632 target->bind_proc = curproxy->bind_proc ?
5633 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005634 }
5635 }
5636 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005637
5638 /* find the target proxy for 'use_backend' rules */
5639 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005640 struct proxy *target;
5641
Alex Williams96532db2009-11-01 21:27:13 -05005642 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005643
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005644 if (!target) {
5645 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5646 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005647 cfgerr++;
5648 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005649 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5650 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005651 cfgerr++;
5652 } else {
5653 free((void *)rule->be.name);
5654 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005655 /* we force the backend to be present on at least all of
5656 * the frontend's processes.
5657 */
5658 target->bind_proc = curproxy->bind_proc ?
5659 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005660 }
5661 }
5662
Emeric Brunb982a3d2010-01-04 15:45:53 +01005663 /* find the target table for 'stick' rules */
5664 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5665 struct proxy *target;
5666
Emeric Brun1d33b292010-01-04 15:47:17 +01005667 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5668 if (mrule->flags & STK_IS_STORE)
5669 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5670
Emeric Brunb982a3d2010-01-04 15:45:53 +01005671 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005672 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005673 else
5674 target = curproxy;
5675
5676 if (!target) {
5677 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5678 curproxy->id, mrule->table.name);
5679 cfgerr++;
5680 }
5681 else if (target->table.size == 0) {
5682 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5683 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5684 cfgerr++;
5685 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005686 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005687 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5688 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5689 cfgerr++;
5690 }
5691 else {
5692 free((void *)mrule->table.name);
5693 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005694 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005695 }
5696 }
5697
5698 /* find the target table for 'store response' rules */
5699 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5700 struct proxy *target;
5701
Emeric Brun1d33b292010-01-04 15:47:17 +01005702 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5703
Emeric Brunb982a3d2010-01-04 15:45:53 +01005704 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005705 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005706 else
5707 target = curproxy;
5708
5709 if (!target) {
5710 Alert("Proxy '%s': unable to find store table '%s'.\n",
5711 curproxy->id, mrule->table.name);
5712 cfgerr++;
5713 }
5714 else if (target->table.size == 0) {
5715 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5716 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5717 cfgerr++;
5718 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005719 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005720 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5721 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5722 cfgerr++;
5723 }
5724 else {
5725 free((void *)mrule->table.name);
5726 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005727 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005728 }
5729 }
5730
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005731 /* find the target table for 'tcp-request' layer 4 rules */
5732 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5733 struct proxy *target;
5734
Willy Tarreau56123282010-08-06 19:06:56 +02005735 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005736 continue;
5737
5738 if (trule->act_prm.trk_ctr.table.n)
5739 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5740 else
5741 target = curproxy;
5742
5743 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005744 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5745 curproxy->id, trule->act_prm.trk_ctr.table.n,
5746 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005747 cfgerr++;
5748 }
5749 else if (target->table.size == 0) {
5750 Alert("Proxy '%s': table '%s' used but not configured.\n",
5751 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5752 cfgerr++;
5753 }
5754 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005755 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 +02005756 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5757 cfgerr++;
5758 }
5759 else {
5760 free(trule->act_prm.trk_ctr.table.n);
5761 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005762 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005763 * to pass a list of counters to track and allocate them right here using
5764 * stktable_alloc_data_type().
5765 */
5766 }
5767 }
5768
Willy Tarreaud1f96522010-08-03 19:34:32 +02005769 /* find the target table for 'tcp-request' layer 6 rules */
5770 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5771 struct proxy *target;
5772
Willy Tarreau56123282010-08-06 19:06:56 +02005773 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005774 continue;
5775
5776 if (trule->act_prm.trk_ctr.table.n)
5777 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5778 else
5779 target = curproxy;
5780
5781 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005782 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5783 curproxy->id, trule->act_prm.trk_ctr.table.n,
5784 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005785 cfgerr++;
5786 }
5787 else if (target->table.size == 0) {
5788 Alert("Proxy '%s': table '%s' used but not configured.\n",
5789 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5790 cfgerr++;
5791 }
5792 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005793 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 +02005794 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5795 cfgerr++;
5796 }
5797 else {
5798 free(trule->act_prm.trk_ctr.table.n);
5799 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005800 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005801 * to pass a list of counters to track and allocate them right here using
5802 * stktable_alloc_data_type().
5803 */
5804 }
5805 }
5806
Emeric Brun32da3c42010-09-23 18:39:19 +02005807 if (curproxy->table.peers.name) {
5808 struct peers *curpeers = peers;
5809
5810 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5811 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5812 free((void *)curproxy->table.peers.name);
5813 curproxy->table.peers.p = peers;
5814 break;
5815 }
5816 }
5817
5818 if (!curpeers) {
5819 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5820 curproxy->id, curproxy->table.peers.name);
5821 cfgerr++;
5822 }
5823 else if (!curpeers->peers_fe) {
5824 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5825 curproxy->id, curpeers->id);
5826 cfgerr++;
5827 }
5828 }
5829
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005830 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5831 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005832 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5833 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5834 "proxy", curproxy->id);
5835 cfgerr++;
5836 goto out_uri_auth_compat;
5837 }
5838
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005839 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005840 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005841 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005842 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005843
Willy Tarreau95fa4692010-02-01 13:05:50 +01005844 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5845 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005846
5847 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005848 uri_auth_compat_req[i++] = "realm";
5849 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5850 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005851
Willy Tarreau95fa4692010-02-01 13:05:50 +01005852 uri_auth_compat_req[i++] = "unless";
5853 uri_auth_compat_req[i++] = "{";
5854 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5855 uri_auth_compat_req[i++] = "}";
5856 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005857
Willy Tarreau95fa4692010-02-01 13:05:50 +01005858 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5859 if (!req_acl) {
5860 cfgerr++;
5861 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005862 }
5863
Willy Tarreau95fa4692010-02-01 13:05:50 +01005864 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5865
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005866 if (curproxy->uri_auth->auth_realm) {
5867 free(curproxy->uri_auth->auth_realm);
5868 curproxy->uri_auth->auth_realm = NULL;
5869 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005870
5871 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005872 }
5873out_uri_auth_compat:
5874
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005875 cfgerr += acl_find_targets(curproxy);
5876
Willy Tarreau2738a142006-07-08 17:28:09 +02005877 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005878 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005879 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005880 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005881 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005882 " | While not properly invalid, you will certainly encounter various problems\n"
5883 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005884 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005885 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005886 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005887 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005888
Willy Tarreau1fa31262007-12-03 00:36:16 +01005889 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5890 * We must still support older configurations, so let's find out whether those
5891 * parameters have been set or must be copied from contimeouts.
5892 */
5893 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005894 if (!curproxy->timeout.tarpit ||
5895 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005896 /* tarpit timeout not set. We search in the following order:
5897 * default.tarpit, curr.connect, default.connect.
5898 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005899 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005900 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005901 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005902 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005903 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005904 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005905 }
5906 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005907 (!curproxy->timeout.queue ||
5908 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005909 /* queue timeout not set. We search in the following order:
5910 * default.queue, curr.connect, default.connect.
5911 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005912 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005913 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005914 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005915 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005916 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005917 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005918 }
5919 }
5920
Willy Tarreau07a54902010-03-29 18:33:29 +02005921 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005922 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5923 curproxy->check_req = (char *)malloc(curproxy->check_len);
5924 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005925 }
5926
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005927 /* The small pools required for the capture lists */
5928 if (curproxy->nb_req_cap)
5929 curproxy->req_cap_pool = create_pool("ptrcap",
5930 curproxy->nb_req_cap * sizeof(char *),
5931 MEM_F_SHARED);
5932 if (curproxy->nb_rsp_cap)
5933 curproxy->rsp_cap_pool = create_pool("ptrcap",
5934 curproxy->nb_rsp_cap * sizeof(char *),
5935 MEM_F_SHARED);
5936
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005937 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5938 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5939 MEM_F_SHARED);
5940
Willy Tarreau86034312006-12-29 00:10:33 +01005941 /* for backwards compatibility with "listen" instances, if
5942 * fullconn is not set but maxconn is set, then maxconn
5943 * is used.
5944 */
5945 if (!curproxy->fullconn)
5946 curproxy->fullconn = curproxy->maxconn;
5947
Willy Tarreaubaaee002006-06-26 02:48:02 +02005948 /* first, we will invert the servers list order */
5949 newsrv = NULL;
5950 while (curproxy->srv) {
5951 struct server *next;
5952
5953 next = curproxy->srv->next;
5954 curproxy->srv->next = newsrv;
5955 newsrv = curproxy->srv;
5956 if (!next)
5957 break;
5958 curproxy->srv = next;
5959 }
5960
Willy Tarreaudd701652010-05-25 23:03:02 +02005961 /* assign automatic UIDs to servers which don't have one yet */
5962 next_id = 1;
5963 newsrv = curproxy->srv;
5964 while (newsrv != NULL) {
5965 if (!newsrv->puid) {
5966 /* server ID not set, use automatic numbering with first
5967 * spare entry starting with next_svid.
5968 */
5969 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5970 newsrv->conf.id.key = newsrv->puid = next_id;
5971 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5972 }
5973 next_id++;
5974 newsrv = newsrv->next;
5975 }
5976
Willy Tarreau20697042007-11-15 23:26:18 +01005977 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005978 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005979
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005980 /* We have to initialize the server lookup mechanism depending
5981 * on what LB algorithm was choosen.
5982 */
5983
5984 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5985 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5986 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005987 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5988 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5989 init_server_map(curproxy);
5990 } else {
5991 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5992 fwrr_init_server_groups(curproxy);
5993 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005994 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005995
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005996 case BE_LB_KIND_LC:
5997 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005998 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005999 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006000
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006001 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006002 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6003 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6004 chash_init_server_tree(curproxy);
6005 } else {
6006 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6007 init_server_map(curproxy);
6008 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006009 break;
6010 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006011
6012 if (curproxy->options & PR_O_LOGASAP)
6013 curproxy->to_log &= ~LW_BYTES;
6014
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006015 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6016 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6017 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6018 proxy_type_str(curproxy), curproxy->id);
6019 err_code |= ERR_WARN;
6020 }
6021
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006022 if (curproxy->mode != PR_MODE_HTTP) {
6023 int optnum;
6024
6025 if (curproxy->options & PR_O_COOK_ANY) {
6026 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6027 proxy_type_str(curproxy), curproxy->id);
6028 err_code |= ERR_WARN;
6029 }
6030
6031 if (curproxy->uri_auth) {
6032 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6033 proxy_type_str(curproxy), curproxy->id);
6034 err_code |= ERR_WARN;
6035 curproxy->uri_auth = NULL;
6036 }
6037
6038 if (curproxy->options & PR_O_FWDFOR) {
6039 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6040 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6041 err_code |= ERR_WARN;
6042 curproxy->options &= ~PR_O_FWDFOR;
6043 }
6044
6045 if (curproxy->options & PR_O_ORGTO) {
6046 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6047 "originalto", proxy_type_str(curproxy), curproxy->id);
6048 err_code |= ERR_WARN;
6049 curproxy->options &= ~PR_O_ORGTO;
6050 }
6051
6052 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6053 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6054 (curproxy->cap & cfg_opts[optnum].cap) &&
6055 (curproxy->options & cfg_opts[optnum].val)) {
6056 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6057 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6058 err_code |= ERR_WARN;
6059 curproxy->options &= ~cfg_opts[optnum].val;
6060 }
6061 }
6062
6063 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6064 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6065 (curproxy->cap & cfg_opts2[optnum].cap) &&
6066 (curproxy->options2 & cfg_opts2[optnum].val)) {
6067 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6068 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6069 err_code |= ERR_WARN;
6070 curproxy->options2 &= ~cfg_opts2[optnum].val;
6071 }
6072 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006073
Willy Tarreauefa5f512010-03-30 20:13:29 +02006074#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006075 if (curproxy->bind_hdr_occ) {
6076 curproxy->bind_hdr_occ = 0;
6077 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6078 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6079 err_code |= ERR_WARN;
6080 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006081#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006082 }
6083
Willy Tarreaubaaee002006-06-26 02:48:02 +02006084 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006085 * ensure that we're not cross-dressing a TCP server into HTTP.
6086 */
6087 newsrv = curproxy->srv;
6088 while (newsrv != NULL) {
6089 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006090 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6091 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006092 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006093 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006094
Willy Tarreauefa5f512010-03-30 20:13:29 +02006095#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006096 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6097 newsrv->bind_hdr_occ = 0;
6098 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6099 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6100 err_code |= ERR_WARN;
6101 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006102#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006103 newsrv = newsrv->next;
6104 }
6105
6106 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006107 * If this server supports a maxconn parameter, it needs a dedicated
6108 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006109 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006110 */
6111 newsrv = curproxy->srv;
6112 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006113 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006114 /* Only 'minconn' was specified, or it was higher than or equal
6115 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6116 * this will avoid further useless expensive computations.
6117 */
6118 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006119 } else if (newsrv->maxconn && !newsrv->minconn) {
6120 /* minconn was not specified, so we set it to maxconn */
6121 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006122 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006123 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6124 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006125 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006126 }
6127
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006128 if (newsrv->trackit) {
6129 struct proxy *px;
6130 struct server *srv;
6131 char *pname, *sname;
6132
6133 pname = newsrv->trackit;
6134 sname = strrchr(pname, '/');
6135
6136 if (sname)
6137 *sname++ = '\0';
6138 else {
6139 sname = pname;
6140 pname = NULL;
6141 }
6142
6143 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006144 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006145 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006146 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6147 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006148 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006149 cfgerr++;
6150 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006151 }
6152 } else
6153 px = curproxy;
6154
6155 srv = findserver(px, sname);
6156 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006157 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6158 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006159 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006160 cfgerr++;
6161 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006162 }
6163
6164 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006165 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006166 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006167 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006168 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006169 cfgerr++;
6170 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006171 }
6172
6173 if (curproxy != px &&
6174 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006175 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006176 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006177 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006178 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006179 cfgerr++;
6180 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006181 }
6182
6183 newsrv->tracked = srv;
6184 newsrv->tracknext = srv->tracknext;
6185 srv->tracknext = newsrv;
6186
6187 free(newsrv->trackit);
6188 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006189 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 newsrv = newsrv->next;
6191 }
6192
Willy Tarreauc1a21672009-08-16 22:37:44 +02006193 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006194 curproxy->accept = frontend_accept;
6195
Willy Tarreauc1a21672009-08-16 22:37:44 +02006196 if (curproxy->tcp_req.inspect_delay ||
6197 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006198 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006199
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006200 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006201 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006202 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006203 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006204
6205 /* both TCP and HTTP must check switching rules */
6206 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6207 }
6208
6209 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006210 if (curproxy->tcp_req.inspect_delay ||
6211 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6212 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6213
Emeric Brun97679e72010-09-23 17:56:44 +02006214 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6215 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6216
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006217 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006218 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006219 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006220 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006221
6222 /* If the backend does requires RDP cookie persistence, we have to
6223 * enable the corresponding analyser.
6224 */
6225 if (curproxy->options2 & PR_O2_RDPC_PRST)
6226 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6227 }
6228
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006229 listener = NULL;
6230 while (curproxy->listen) {
6231 struct listener *next;
6232
6233 next = curproxy->listen->next;
6234 curproxy->listen->next = listener;
6235 listener = curproxy->listen;
6236
6237 if (!next)
6238 break;
6239
6240 curproxy->listen = next;
6241 }
6242
Willy Tarreaue6b98942007-10-29 01:09:36 +01006243 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006244 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006245 listener = curproxy->listen;
6246 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006247 if (!listener->luid) {
6248 /* listener ID not set, use automatic numbering with first
6249 * spare entry starting with next_luid.
6250 */
6251 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6252 listener->conf.id.key = listener->luid = next_id;
6253 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006254 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006255 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006256
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006257 /* enable separate counters */
6258 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6259 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6260 if (!listener->name) {
6261 sprintf(trash, "sock-%d", listener->luid);
6262 listener->name = strdup(trash);
6263 }
6264 }
6265
Willy Tarreaue6b98942007-10-29 01:09:36 +01006266 if (curproxy->options & PR_O_TCP_NOLING)
6267 listener->options |= LI_O_NOLINGER;
6268 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006269 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006270 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006271 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006272 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006273 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006274 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006275
Willy Tarreau8a956912010-10-15 14:27:08 +02006276 if (listener->options & LI_O_ACC_PROXY)
6277 listener->analysers |= AN_REQ_DECODE_PROXY;
6278
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006279 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6280 listener->options |= LI_O_TCP_RULES;
6281
Willy Tarreaude3041d2010-05-31 10:56:17 +02006282 if (curproxy->mon_mask.s_addr)
6283 listener->options |= LI_O_CHK_MONNET;
6284
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006285 /* smart accept mode is automatic in HTTP mode */
6286 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6287 (curproxy->mode == PR_MODE_HTTP &&
6288 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6289 listener->options |= LI_O_NOQUICKACK;
6290
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006291 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006292 listener = listener->next;
6293 }
6294
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006295 /* Check multi-process mode compatibility for the current proxy */
6296 if (global.nbproc > 1) {
6297 int nbproc = 0;
6298 if (curproxy->bind_proc) {
6299 int proc;
6300 for (proc = 0; proc < global.nbproc; proc++) {
6301 if (curproxy->bind_proc & (1 << proc)) {
6302 nbproc++;
6303 }
6304 }
6305 } else {
6306 nbproc = global.nbproc;
6307 }
6308 if (curproxy->table.peers.name) {
6309 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6310 curproxy->id);
6311 cfgerr++;
6312 }
6313 if (nbproc > 1) {
6314 if (curproxy->uri_auth) {
6315 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6316 curproxy->id);
6317 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6318 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6319 curproxy->id);
6320 }
6321 }
6322 if (curproxy->appsession_name) {
6323 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6324 curproxy->id);
6325 }
6326 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6327 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6328 curproxy->id);
6329 }
6330 }
6331 }
6332
Willy Tarreaubaaee002006-06-26 02:48:02 +02006333 curproxy = curproxy->next;
6334 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006335
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006336 /* Check multi-process mode compatibility */
6337 if (global.nbproc > 1) {
6338 if (global.stats_fe) {
6339 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6340 }
6341 }
6342
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006343 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6344 struct auth_users *curuser;
6345 int g;
6346
6347 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6348 unsigned int group_mask = 0;
6349 char *group = NULL;
6350
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006351 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006352 continue;
6353
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006354 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006355
6356 for (g = 0; g < curuserlist->grpcnt; g++)
6357 if (!strcmp(curuserlist->groups[g], group))
6358 break;
6359
6360 if (g == curuserlist->grpcnt) {
6361 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6362 curuserlist->name, group, curuser->user);
6363 err_code |= ERR_ALERT | ERR_FATAL;
6364 goto out;
6365 }
6366
6367 group_mask |= (1 << g);
6368 }
6369
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006370 free(curuser->u.groups);
6371 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006372 }
6373
6374 for (g = 0; g < curuserlist->grpcnt; g++) {
6375 char *user = NULL;
6376
6377 if (!curuserlist->groupusers[g])
6378 continue;
6379
6380 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6381 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6382 if (!strcmp(curuser->user, user))
6383 break;
6384
6385 if (!curuser) {
6386 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6387 curuserlist->name, user, curuserlist->groups[g]);
6388 err_code |= ERR_ALERT | ERR_FATAL;
6389 goto out;
6390 }
6391
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006392 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006393 }
6394
6395 free(curuserlist->groupusers[g]);
6396 }
6397
6398 free(curuserlist->groupusers);
6399
6400#ifdef DEBUG_AUTH
6401 for (g = 0; g < curuserlist->grpcnt; g++) {
6402 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6403
6404 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6405 if (curuser->group_mask & (1 << g))
6406 fprintf(stderr, " %s", curuser->user);
6407 }
6408
6409 fprintf(stderr, "\n");
6410 }
6411#endif
6412
6413 }
6414
Willy Tarreau056f5682010-06-06 15:51:11 +02006415 /* initialize stick-tables on backend capable proxies. This must not
6416 * be done earlier because the data size may be discovered while parsing
6417 * other proxies.
6418 */
6419 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006420 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006421
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006422 /*
6423 * Recount currently required checks.
6424 */
6425
6426 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6427 int optnum;
6428
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006429 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6430 if (curproxy->options & cfg_opts[optnum].val)
6431 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006432
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006433 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6434 if (curproxy->options2 & cfg_opts2[optnum].val)
6435 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006436 }
6437
Willy Tarreaubb925012009-07-23 13:36:36 +02006438 if (cfgerr > 0)
6439 err_code |= ERR_ALERT | ERR_FATAL;
6440 out:
6441 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006442}
6443
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006444/*
6445 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6446 * parsing sessions.
6447 */
6448void cfg_register_keywords(struct cfg_kw_list *kwl)
6449{
6450 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6451}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006453/*
6454 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6455 */
6456void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6457{
6458 LIST_DEL(&kwl->list);
6459 LIST_INIT(&kwl->list);
6460}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006461
6462/*
6463 * Local variables:
6464 * c-indent-level: 8
6465 * c-basic-offset: 8
6466 * End:
6467 */