blob: 124e599b3ea7285e72a3542933317851089c2e3d [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 }
969 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
970 if (global.spread_checks != 0) {
971 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200972 err_code |= ERR_ALERT;
973 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200974 }
975 if (*(args[1]) == 0) {
976 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200979 }
980 global.spread_checks = atol(args[1]);
981 if (global.spread_checks < 0 || global.spread_checks > 50) {
982 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200983 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 }
986 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200987 struct cfg_kw_list *kwl;
988 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200989 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200990
991 list_for_each_entry(kwl, &cfg_keywords.list, list) {
992 for (index = 0; kwl->kw[index].kw != NULL; index++) {
993 if (kwl->kw[index].section != CFG_GLOBAL)
994 continue;
995 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
996 /* prepare error message just in case */
997 snprintf(trash, sizeof(trash),
998 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200999 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1000 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001001 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001002 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001003 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001004 else if (rc > 0) {
1005 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001006 err_code |= ERR_WARN;
1007 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001008 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001009 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001010 }
1011 }
1012 }
1013
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001015 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001017
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 out:
1019 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020}
1021
Willy Tarreau97cb7802010-01-03 20:23:58 +01001022/* Perform the most basic initialization of a proxy :
1023 * memset(), list_init(*), reset_timeouts(*).
1024 */
1025static void init_new_proxy(struct proxy *p)
1026{
1027 memset(p, 0, sizeof(struct proxy));
1028 LIST_INIT(&p->pendconns);
1029 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001030 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001031 LIST_INIT(&p->block_cond);
1032 LIST_INIT(&p->redirect_rules);
1033 LIST_INIT(&p->mon_fail_cond);
1034 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001035 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001036 LIST_INIT(&p->sticking_rules);
1037 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001038 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001039 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001040 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001041 LIST_INIT(&p->req_add);
1042 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001043
1044 /* Timeouts are defined as -1 */
1045 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001046 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001047}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001049void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001051 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 defproxy.mode = PR_MODE_TCP;
1053 defproxy.state = PR_STNEW;
1054 defproxy.maxconn = cfg_maxpconn;
1055 defproxy.conn_retries = CONN_RETRIES;
1056 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001057
1058 defproxy.defsrv.inter = DEF_CHKINTR;
1059 defproxy.defsrv.fastinter = 0;
1060 defproxy.defsrv.downinter = 0;
1061 defproxy.defsrv.rise = DEF_RISETIME;
1062 defproxy.defsrv.fall = DEF_FALLTIME;
1063 defproxy.defsrv.check_port = 0;
1064 defproxy.defsrv.maxqueue = 0;
1065 defproxy.defsrv.minconn = 0;
1066 defproxy.defsrv.maxconn = 0;
1067 defproxy.defsrv.slowstart = 0;
1068 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1069 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1070 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071}
1072
Willy Tarreauade5ec42010-01-28 19:33:49 +01001073
1074static int create_cond_regex_rule(const char *file, int line,
1075 struct proxy *px, int dir, int action, int flags,
1076 const char *cmd, const char *reg, const char *repl,
1077 const char **cond_start)
1078{
1079 regex_t *preg = NULL;
1080 const char *err;
1081 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001082 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001083
1084 if (px == &defproxy) {
1085 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto err;
1088 }
1089
1090 if (*reg == 0) {
1091 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto err;
1094 }
1095
1096 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1097 err_code |= ERR_WARN;
1098
Willy Tarreau5321c422010-01-28 20:35:13 +01001099 if (cond_start &&
1100 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1101 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1102 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1103 file, line, cmd);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto err;
1106 }
1107 }
1108 else if (cond_start && **cond_start) {
1109 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1110 file, line, cmd, *cond_start);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto err;
1113 }
1114
1115 if (dir == ACL_DIR_REQ)
1116 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001117 else
1118 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001119
Willy Tarreauade5ec42010-01-28 19:33:49 +01001120 preg = calloc(1, sizeof(regex_t));
1121 if (!preg) {
1122 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1123 err_code = ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
1127 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1128 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1129 err_code = ERR_ALERT | ERR_FATAL;
1130 goto err;
1131 }
1132
1133 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001134 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001135 if (repl && err) {
1136 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1137 file, line, cmd, *err);
1138 err_code |= ERR_ALERT | ERR_FATAL;
1139 goto err;
1140 }
1141
1142 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1143 err_code |= ERR_WARN;
1144
1145 return err_code;
1146 err:
1147 free(preg);
1148 return err_code;
1149}
1150
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001152 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001153 * Returns the error code, 0 if OK, or any combination of :
1154 * - ERR_ABORT: must abort ASAP
1155 * - ERR_FATAL: we can continue parsing but not start the service
1156 * - ERR_WARN: a warning has been emitted
1157 * - ERR_ALERT: an alert has been emitted
1158 * Only the two first ones can stop processing, the two others are just
1159 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001161int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1162{
1163 static struct peers *curpeers = NULL;
1164 struct peer *newpeer = NULL;
1165 const char *err;
1166 int err_code = 0;
1167
1168 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1169
1170 err = invalid_char(args[1]);
1171 if (err) {
1172 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1173 file, linenum, *err, args[0], args[1]);
1174 err_code |= ERR_ALERT | ERR_FATAL;
1175 }
1176
1177 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1178 /*
1179 * If there are two proxies with the same name only following
1180 * combinations are allowed:
1181 */
1182 if (strcmp(curpeers->id, args[1]) == 0) {
1183 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1184 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1185 err_code |= ERR_WARN;
1186 }
1187 }
1188
1189 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1190 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1191 err_code |= ERR_ALERT | ERR_ABORT;
1192 goto out;
1193 }
1194
1195 curpeers->next = peers;
1196 peers = curpeers;
1197 curpeers->conf.file = file;
1198 curpeers->conf.line = linenum;
1199 curpeers->last_change = now.tv_sec;
1200 curpeers->id = strdup(args[1]);
1201 }
1202 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1203 char *rport, *raddr;
1204 short realport = 0;
1205 struct sockaddr_in *sk;
1206
1207 if (!*args[2]) {
1208 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1209 file, linenum, args[0]);
1210 err_code |= ERR_ALERT | ERR_FATAL;
1211 goto out;
1212 }
1213
1214 err = invalid_char(args[1]);
1215 if (err) {
1216 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1217 file, linenum, *err, args[1]);
1218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
1220 }
1221
1222 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1224 err_code |= ERR_ALERT | ERR_ABORT;
1225 goto out;
1226 }
1227
1228 /* the peers are linked backwards first */
1229 curpeers->count++;
1230 newpeer->next = curpeers->remote;
1231 curpeers->remote = newpeer;
1232 newpeer->peers = curpeers;
1233 newpeer->conf.file = file;
1234 newpeer->conf.line = linenum;
1235
1236 newpeer->last_change = now.tv_sec;
1237 newpeer->id = strdup(args[1]);
1238
1239 raddr = strdup(args[2]);
1240 rport = strchr(raddr, ':');
1241 if (rport) {
1242 *rport++ = 0;
1243 realport = atol(rport);
1244 }
1245 if (!realport) {
1246 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250
1251 sk = str2sa(raddr);
1252 free(raddr);
1253 if (!sk) {
1254 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto out;
1257 }
1258 newpeer->addr = *sk;
1259 newpeer->addr.sin_port = htons(realport);
1260
1261 if (strcmp(newpeer->id, localpeer) == 0) {
1262 /* Current is local peer, it define a frontend */
1263 newpeer->local = 1;
1264
1265 if (!curpeers->peers_fe) {
1266 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1267 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1268 err_code |= ERR_ALERT | ERR_ABORT;
1269 goto out;
1270 }
1271 curpeers->peers_fe->parent = curpeers;
1272
1273 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1274 LIST_INIT(&(curpeers->peers_fe)->acl);
1275 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1276 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1277 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1278 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1279 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1280 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1281
1282 proxy_reset_timeouts(curpeers->peers_fe);
1283
1284 curpeers->peers_fe->last_change = now.tv_sec;
1285 curpeers->peers_fe->id = strdup(args[1]);
1286 curpeers->peers_fe->cap = PR_CAP_FE;
1287 curpeers->peers_fe->maxconn = 65000;
1288 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1289 curpeers->peers_fe->timeout.connect = 5000;
1290 curpeers->peers_fe->accept = peer_accept;
1291 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
1292 if (!str2listener(args[2], curpeers->peers_fe)) {
1293 err_code |= ERR_FATAL;
1294 goto out;
1295 }
1296 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1297 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1298 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1299 curpeers->peers_fe->listen->accept = session_accept;
1300 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1301 curpeers->peers_fe->listen->handler = process_session;
1302 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1303 }
1304 }
1305 } /* neither "peer" nor "peers" */
1306 else if (*args[0] != 0) {
1307 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
1310 }
1311
1312out:
1313 return err_code;
1314}
1315
1316
Willy Tarreau3842f002009-06-14 11:39:52 +02001317int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
1319 static struct proxy *curproxy = NULL;
1320 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001321 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001322 int rc;
1323 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001324 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001325 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326
Willy Tarreau977b8e42006-12-29 14:19:17 +01001327 if (!strcmp(args[0], "listen"))
1328 rc = PR_CAP_LISTEN;
1329 else if (!strcmp(args[0], "frontend"))
1330 rc = PR_CAP_FE | PR_CAP_RS;
1331 else if (!strcmp(args[0], "backend"))
1332 rc = PR_CAP_BE | PR_CAP_RS;
1333 else if (!strcmp(args[0], "ruleset"))
1334 rc = PR_CAP_RS;
1335 else
1336 rc = PR_CAP_NONE;
1337
1338 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 if (!*args[1]) {
1340 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1341 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1342 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001343 err_code |= ERR_ALERT | ERR_ABORT;
1344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001345 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001346
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001347 err = invalid_char(args[1]);
1348 if (err) {
1349 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1350 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001351 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001352 }
1353
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001354 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1355 /*
1356 * If there are two proxies with the same name only following
1357 * combinations are allowed:
1358 *
1359 * listen backend frontend ruleset
1360 * listen - - - -
1361 * backend - - OK -
1362 * frontend - OK - -
1363 * ruleset - - - -
1364 */
1365
1366 if (!strcmp(curproxy->id, args[1]) &&
1367 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1368 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001369 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1370 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1371 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001372 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001373 }
1374 }
1375
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1377 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001378 err_code |= ERR_ALERT | ERR_ABORT;
1379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001381
Willy Tarreau97cb7802010-01-03 20:23:58 +01001382 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 curproxy->next = proxy;
1384 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001385 curproxy->conf.file = file;
1386 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001387 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001389 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390
1391 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001392 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001393 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001394 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001395 err_code |= ERR_FATAL;
1396 goto out;
1397 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001398 new = curproxy->listen;
1399 while (new != last) {
1400 new->conf.file = file;
1401 new->conf.line = linenum;
1402 new = new->next;
1403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 global.maxsock++;
1405 }
1406
1407 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001408 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001409 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001410
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001413 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001414 curproxy->no_options = defproxy.no_options;
1415 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001416 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001417 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001418 curproxy->except_net = defproxy.except_net;
1419 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001420 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001421 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001423 if (defproxy.fwdfor_hdr_len) {
1424 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1425 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1426 }
1427
Willy Tarreaub86db342009-11-30 11:50:16 +01001428 if (defproxy.orgto_hdr_len) {
1429 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1430 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1431 }
1432
Willy Tarreau977b8e42006-12-29 14:19:17 +01001433 if (curproxy->cap & PR_CAP_FE) {
1434 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001435 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001436 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001437
1438 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001439 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1440 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001441
1442 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444
Willy Tarreau977b8e42006-12-29 14:19:17 +01001445 if (curproxy->cap & PR_CAP_BE) {
1446 curproxy->fullconn = defproxy.fullconn;
1447 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001449 if (defproxy.check_req) {
1450 curproxy->check_req = calloc(1, defproxy.check_len);
1451 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1452 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001453 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454
Willy Tarreau977b8e42006-12-29 14:19:17 +01001455 if (defproxy.cookie_name)
1456 curproxy->cookie_name = strdup(defproxy.cookie_name);
1457 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001458 if (defproxy.cookie_domain)
1459 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001460
Willy Tarreau31936852010-10-06 16:59:56 +02001461 if (defproxy.cookie_maxidle)
1462 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1463
1464 if (defproxy.cookie_maxlife)
1465 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1466
Emeric Brun647caf12009-06-30 17:57:00 +02001467 if (defproxy.rdp_cookie_name)
1468 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1469 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1470
Willy Tarreau01732802007-11-01 22:48:15 +01001471 if (defproxy.url_param_name)
1472 curproxy->url_param_name = strdup(defproxy.url_param_name);
1473 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001474
Benoitaffb4812009-03-25 13:02:10 +01001475 if (defproxy.hh_name)
1476 curproxy->hh_name = strdup(defproxy.hh_name);
1477 curproxy->hh_len = defproxy.hh_len;
1478 curproxy->hh_match_domain = defproxy.hh_match_domain;
1479
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001480 if (defproxy.iface_name)
1481 curproxy->iface_name = strdup(defproxy.iface_name);
1482 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001485 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001486 if (defproxy.capture_name)
1487 curproxy->capture_name = strdup(defproxy.capture_name);
1488 curproxy->capture_namelen = defproxy.capture_namelen;
1489 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001493 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001494 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001495 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001496 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497 curproxy->uri_auth = defproxy.uri_auth;
1498 curproxy->mon_net = defproxy.mon_net;
1499 curproxy->mon_mask = defproxy.mon_mask;
1500 if (defproxy.monitor_uri)
1501 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1502 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001503 if (defproxy.defbe.name)
1504 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001505 }
1506
1507 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001508 curproxy->timeout.connect = defproxy.timeout.connect;
1509 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001510 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001511 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001512 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001513 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001514 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001515 curproxy->source_addr = defproxy.source_addr;
1516 }
1517
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518 curproxy->mode = defproxy.mode;
1519 curproxy->logfac1 = defproxy.logfac1;
1520 curproxy->logsrv1 = defproxy.logsrv1;
1521 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001522 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 curproxy->logfac2 = defproxy.logfac2;
1524 curproxy->logsrv2 = defproxy.logsrv2;
1525 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001526 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001528 curproxy->conf.used_listener_id = EB_ROOT;
1529 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001530
Willy Tarreau93893792009-07-23 13:19:11 +02001531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 }
1533 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1534 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001535 /* FIXME-20070101: we should do this too at the end of the
1536 * config parsing to free all default values.
1537 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001538 free(defproxy.check_req);
1539 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001540 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001541 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001542 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001543 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001544 free(defproxy.capture_name);
1545 free(defproxy.monitor_uri);
1546 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001547 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001548 free(defproxy.fwdfor_hdr_name);
1549 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001550 free(defproxy.orgto_hdr_name);
1551 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001552
Willy Tarreaua534fea2008-08-03 12:19:50 +02001553 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001554 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001555
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 /* we cannot free uri_auth because it might already be used */
1557 init_default_instance();
1558 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001559 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 }
1562 else if (curproxy == NULL) {
1563 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001564 err_code |= ERR_ALERT | ERR_FATAL;
1565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 }
1567
Willy Tarreau977b8e42006-12-29 14:19:17 +01001568
1569 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001571 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001572 int cur_arg;
1573
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 if (curproxy == &defproxy) {
1575 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
1577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001579 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001580 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581
Emeric Bruned760922010-10-22 17:59:25 +02001582 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001583 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001588
1589 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001590
1591 /* NOTE: the following line might create several listeners if there
1592 * are comma-separated IPs or port ranges. So all further processing
1593 * will have to be applied to all listeners created after last_listen.
1594 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001595 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
1597 goto out;
1598 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001599
Willy Tarreau90a570f2009-10-04 20:54:54 +02001600 new_listen = curproxy->listen;
1601 while (new_listen != last_listen) {
1602 new_listen->conf.file = file;
1603 new_listen->conf.line = linenum;
1604 new_listen = new_listen->next;
1605 }
1606
Emeric Bruned760922010-10-22 17:59:25 +02001607 /* Set default global rights and owner for unix bind */
1608 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1609 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1610 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001611 cur_arg = 2;
1612 while (*(args[cur_arg])) {
1613 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1614#ifdef SO_BINDTODEVICE
1615 struct listener *l;
1616
Emeric Bruned760922010-10-22 17:59:25 +02001617 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1618 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1619 file, linenum, args[0], args[cur_arg]);
1620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
1622 }
1623
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001624 if (!*args[cur_arg + 1]) {
1625 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001629 }
1630
1631 for (l = curproxy->listen; l != last_listen; l = l->next)
1632 l->interface = strdup(args[cur_arg + 1]);
1633
1634 global.last_checks |= LSTCHK_NETADM;
1635
1636 cur_arg += 2;
1637 continue;
1638#else
1639 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1640 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001643#endif
1644 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001645 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1646#ifdef TCP_MAXSEG
1647 struct listener *l;
1648 int mss;
1649
Emeric Bruned760922010-10-22 17:59:25 +02001650 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1651 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1652 file, linenum, args[0], args[cur_arg]);
1653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
1655 }
1656
Willy Tarreaube1b9182009-06-14 18:48:19 +02001657 if (!*args[cur_arg + 1]) {
1658 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001662 }
1663
1664 mss = str2uic(args[cur_arg + 1]);
1665 if (mss < 1 || mss > 65535) {
1666 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1667 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001670 }
1671
1672 for (l = curproxy->listen; l != last_listen; l = l->next)
1673 l->maxseg = mss;
1674
1675 cur_arg += 2;
1676 continue;
1677#else
1678 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1679 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001680 err_code |= ERR_ALERT | ERR_FATAL;
1681 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001682#endif
1683 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001684
1685 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1686#ifdef TCP_DEFER_ACCEPT
1687 struct listener *l;
1688
1689 for (l = curproxy->listen; l != last_listen; l = l->next)
1690 l->options |= LI_O_DEF_ACCEPT;
1691
1692 cur_arg ++;
1693 continue;
1694#else
1695 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1696 file, linenum, args[0], args[cur_arg]);
1697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
1699#endif
1700 }
1701
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001702 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001703#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001704 struct listener *l;
1705
Emeric Bruned760922010-10-22 17:59:25 +02001706 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1707 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1708 file, linenum, args[0], args[cur_arg]);
1709 err_code |= ERR_ALERT | ERR_FATAL;
1710 goto out;
1711 }
1712
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001713 for (l = curproxy->listen; l != last_listen; l = l->next)
1714 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001715
1716 cur_arg ++;
1717 continue;
1718#else
1719 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1720 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001723#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001724 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001725
Willy Tarreau8a956912010-10-15 14:27:08 +02001726 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1727 struct listener *l;
1728
1729 for (l = curproxy->listen; l != last_listen; l = l->next)
1730 l->options |= LI_O_ACC_PROXY;
1731
1732 cur_arg ++;
1733 continue;
1734 }
1735
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001736 if (!strcmp(args[cur_arg], "name")) {
1737 struct listener *l;
1738
1739 for (l = curproxy->listen; l != last_listen; l = l->next)
1740 l->name = strdup(args[cur_arg + 1]);
1741
1742 cur_arg += 2;
1743 continue;
1744 }
1745
1746 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001747 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001748 struct listener *l;
1749
1750 if (curproxy->listen->next != last_listen) {
1751 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1752 file, linenum, args[cur_arg]);
1753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
1755 }
1756
1757 if (!*args[cur_arg + 1]) {
1758 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1759 file, linenum, args[cur_arg]);
1760 err_code |= ERR_ALERT | ERR_FATAL;
1761 goto out;
1762 }
1763
1764 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001765 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001766
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001767 if (curproxy->listen->luid <= 0) {
1768 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001769 file, linenum);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001774 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1775 if (node) {
1776 l = container_of(node, struct listener, conf.id);
1777 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1778 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
1781 }
1782 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1783
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001784 cur_arg += 2;
1785 continue;
1786 }
1787
Emeric Bruned760922010-10-22 17:59:25 +02001788 if (!strcmp(args[cur_arg], "mode")) {
1789
1790 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1791 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1792 file, linenum, args[0], args[cur_arg]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1798
1799 cur_arg += 2;
1800 continue;
1801 }
1802
1803 if (!strcmp(args[cur_arg], "uid")) {
1804
1805 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1806 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1807 file, linenum, args[0], args[cur_arg]);
1808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
1810 }
1811
1812 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1813 cur_arg += 2;
1814 continue;
1815 }
1816
1817 if (!strcmp(args[cur_arg], "gid")) {
1818
1819 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1820 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1821 file, linenum, args[0], args[cur_arg]);
1822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
1824 }
1825
1826 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1827 cur_arg += 2;
1828 continue;
1829 }
1830
1831 if (!strcmp(args[cur_arg], "user")) {
1832 struct passwd *user;
1833
1834 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1835 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1836 file, linenum, args[0], args[cur_arg]);
1837 err_code |= ERR_ALERT | ERR_FATAL;
1838 goto out;
1839 }
1840 user = getpwnam(args[cur_arg + 1]);
1841 if (!user) {
1842 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1843 file, linenum, args[0], args[cur_arg + 1 ]);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
1847
1848 curproxy->listen->perm.ux.uid = user->pw_uid;
1849 cur_arg += 2;
1850 continue;
1851 }
1852
1853 if (!strcmp(args[cur_arg], "group")) {
1854 struct group *group;
1855
1856 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1857 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1858 file, linenum, args[0], args[cur_arg]);
1859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
1861 }
1862 group = getgrnam(args[cur_arg + 1]);
1863 if (!group) {
1864 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1865 file, linenum, args[0], args[cur_arg + 1 ]);
1866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
1868 }
1869
1870 curproxy->listen->perm.ux.gid = group->gr_gid;
1871 cur_arg += 2;
1872 continue;
1873 }
1874
Willy Tarreau8a956912010-10-15 14:27:08 +02001875 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 +01001876 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001877 err_code |= ERR_ALERT | ERR_FATAL;
1878 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001879 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882 }
1883 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1884 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1885 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1886 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001890 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001891 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001892
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893 /* flush useless bits */
1894 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001897 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001898 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001899 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001900
Willy Tarreau1c47f852006-07-09 08:22:27 +02001901 if (!*args[1]) {
1902 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1903 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001904 err_code |= ERR_ALERT | ERR_FATAL;
1905 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001906 }
1907
Willy Tarreaua534fea2008-08-03 12:19:50 +02001908 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001909 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001910 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001911 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001912 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1913
Willy Tarreau93893792009-07-23 13:19:11 +02001914 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1917 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1918 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1919 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1920 else {
1921 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 }
1925 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001926 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001927 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001928
1929 if (curproxy == &defproxy) {
1930 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1931 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001934 }
1935
1936 if (!*args[1]) {
1937 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_ALERT | ERR_FATAL;
1940 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001941 }
1942
1943 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001944 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001945
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001946 if (curproxy->uuid <= 0) {
1947 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001948 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001949 err_code |= ERR_ALERT | ERR_FATAL;
1950 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001951 }
1952
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001953 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1954 if (node) {
1955 struct proxy *target = container_of(node, struct proxy, conf.id);
1956 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1957 file, linenum, proxy_type_str(curproxy), curproxy->id,
1958 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1959 err_code |= ERR_ALERT | ERR_FATAL;
1960 goto out;
1961 }
1962 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001963 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001964 else if (!strcmp(args[0], "description")) {
1965 int i, len=0;
1966 char *d;
1967
Cyril Bonté99ed3272010-01-24 23:29:44 +01001968 if (curproxy == &defproxy) {
1969 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1970 file, linenum, args[0]);
1971 err_code |= ERR_ALERT | ERR_FATAL;
1972 goto out;
1973 }
1974
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001975 if (!*args[1]) {
1976 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1977 file, linenum, args[0]);
1978 return -1;
1979 }
1980
1981 for(i=1; *args[i]; i++)
1982 len += strlen(args[i])+1;
1983
1984 d = (char *)calloc(1, len);
1985 curproxy->desc = d;
1986
1987 d += sprintf(d, "%s", args[1]);
1988 for(i=2; *args[i]; i++)
1989 d += sprintf(d, " %s", args[i]);
1990
1991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1993 curproxy->state = PR_STSTOPPED;
1994 }
1995 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1996 curproxy->state = PR_STNEW;
1997 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001998 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1999 int cur_arg = 1;
2000 unsigned int set = 0;
2001
2002 while (*args[cur_arg]) {
2003 int u;
2004 if (strcmp(args[cur_arg], "all") == 0) {
2005 set = 0;
2006 break;
2007 }
2008 else if (strcmp(args[cur_arg], "odd") == 0) {
2009 set |= 0x55555555;
2010 }
2011 else if (strcmp(args[cur_arg], "even") == 0) {
2012 set |= 0xAAAAAAAA;
2013 }
2014 else {
2015 u = str2uic(args[cur_arg]);
2016 if (u < 1 || u > 32) {
2017 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2018 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002021 }
2022 if (u > global.nbproc) {
2023 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2024 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002025 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002026 }
2027 set |= 1 << (u - 1);
2028 }
2029 cur_arg++;
2030 }
2031 curproxy->bind_proc = set;
2032 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002033 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002034 if (curproxy == &defproxy) {
2035 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002036 err_code |= ERR_ALERT | ERR_FATAL;
2037 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002038 }
2039
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002040 err = invalid_char(args[1]);
2041 if (err) {
2042 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2043 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002044 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002045 }
2046
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002047 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2048 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2049 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002052 }
2053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002054 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2055 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002056
Willy Tarreau977b8e42006-12-29 14:19:17 +01002057 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002058 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002059
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 if (*(args[1]) == 0) {
2061 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002066
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002067 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002068 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002069 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002070 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002071 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 curproxy->cookie_name = strdup(args[1]);
2073 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002074
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 cur_arg = 2;
2076 while (*(args[cur_arg])) {
2077 if (!strcmp(args[cur_arg], "rewrite")) {
2078 curproxy->options |= PR_O_COOK_RW;
2079 }
2080 else if (!strcmp(args[cur_arg], "indirect")) {
2081 curproxy->options |= PR_O_COOK_IND;
2082 }
2083 else if (!strcmp(args[cur_arg], "insert")) {
2084 curproxy->options |= PR_O_COOK_INS;
2085 }
2086 else if (!strcmp(args[cur_arg], "nocache")) {
2087 curproxy->options |= PR_O_COOK_NOC;
2088 }
2089 else if (!strcmp(args[cur_arg], "postonly")) {
2090 curproxy->options |= PR_O_COOK_POST;
2091 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002092 else if (!strcmp(args[cur_arg], "preserve")) {
2093 curproxy->options2 |= PR_O2_COOK_PSV;
2094 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 else if (!strcmp(args[cur_arg], "prefix")) {
2096 curproxy->options |= PR_O_COOK_PFX;
2097 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002098 else if (!strcmp(args[cur_arg], "domain")) {
2099 if (!*args[cur_arg + 1]) {
2100 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2101 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002104 }
2105
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002106 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002107 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002108 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2109 " dots nor does not start with a dot."
2110 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002111 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002112 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002113 }
2114
2115 err = invalid_domainchar(args[cur_arg + 1]);
2116 if (err) {
2117 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2118 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002119 err_code |= ERR_ALERT | ERR_FATAL;
2120 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002121 }
2122
Willy Tarreau68a897b2009-12-03 23:28:34 +01002123 if (!curproxy->cookie_domain) {
2124 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2125 } else {
2126 /* one domain was already specified, add another one by
2127 * building the string which will be returned along with
2128 * the cookie.
2129 */
2130 char *new_ptr;
2131 int new_len = strlen(curproxy->cookie_domain) +
2132 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2133 new_ptr = malloc(new_len);
2134 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2135 free(curproxy->cookie_domain);
2136 curproxy->cookie_domain = new_ptr;
2137 }
Willy Tarreau31936852010-10-06 16:59:56 +02002138 cur_arg++;
2139 }
2140 else if (!strcmp(args[cur_arg], "maxidle")) {
2141 unsigned int maxidle;
2142 const char *res;
2143
2144 if (!*args[cur_arg + 1]) {
2145 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2146 file, linenum, args[cur_arg]);
2147 err_code |= ERR_ALERT | ERR_FATAL;
2148 goto out;
2149 }
2150
2151 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2152 if (res) {
2153 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2154 file, linenum, *res, args[cur_arg]);
2155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
2157 }
2158 curproxy->cookie_maxidle = maxidle;
2159 cur_arg++;
2160 }
2161 else if (!strcmp(args[cur_arg], "maxlife")) {
2162 unsigned int maxlife;
2163 const char *res;
2164
2165 if (!*args[cur_arg + 1]) {
2166 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2167 file, linenum, args[cur_arg]);
2168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
2170 }
2171
2172 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2173 if (res) {
2174 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2175 file, linenum, *res, args[cur_arg]);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
2179 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002180 cur_arg++;
2181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002183 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 +02002184 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 }
2188 cur_arg++;
2189 }
2190 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2191 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2192 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002193 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002194 }
2195
2196 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2197 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2198 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002200 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002201
2202 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2203 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2204 file, linenum);
2205 err_code |= ERR_ALERT | ERR_FATAL;
2206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002208 else if (!strcmp(args[0], "persist")) { /* persist */
2209 if (*(args[1]) == 0) {
2210 Alert("parsing [%s:%d] : missing persist method.\n",
2211 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002214 }
2215
2216 if (!strncmp(args[1], "rdp-cookie", 10)) {
2217 curproxy->options2 |= PR_O2_RDPC_PRST;
2218
Emeric Brunb982a3d2010-01-04 15:45:53 +01002219 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002220 const char *beg, *end;
2221
2222 beg = args[1] + 11;
2223 end = strchr(beg, ')');
2224
2225 if (!end || end == beg) {
2226 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2227 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002230 }
2231
2232 free(curproxy->rdp_cookie_name);
2233 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2234 curproxy->rdp_cookie_len = end-beg;
2235 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002236 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002237 free(curproxy->rdp_cookie_name);
2238 curproxy->rdp_cookie_name = strdup("msts");
2239 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2240 }
2241 else { /* syntax */
2242 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2243 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002246 }
2247 }
2248 else {
2249 Alert("parsing [%s:%d] : unknown persist method.\n",
2250 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002253 }
2254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002256 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002258 if (curproxy == &defproxy) {
2259 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
2262 }
2263
Willy Tarreau977b8e42006-12-29 14:19:17 +01002264 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002265 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002266
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002268 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 }
2273 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002274 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 curproxy->appsession_name = strdup(args[1]);
2276 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2277 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002278 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2279 if (err) {
2280 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2281 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002284 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002285 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002286
Willy Tarreau51041c72007-09-09 21:56:53 +02002287 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2288 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_ABORT;
2290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002292
2293 cur_arg = 6;
2294 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002295 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2296 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002297 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002298 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002299 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002300 } else if (!strcmp(args[cur_arg], "prefix")) {
2301 curproxy->options2 |= PR_O2_AS_PFX;
2302 } else if (!strcmp(args[cur_arg], "mode")) {
2303 if (!*args[cur_arg + 1]) {
2304 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2305 file, linenum, args[0], args[cur_arg]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310 cur_arg++;
2311 if (!strcmp(args[cur_arg], "query-string")) {
2312 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2313 curproxy->options2 |= PR_O2_AS_M_QS;
2314 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2315 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2316 curproxy->options2 |= PR_O2_AS_M_PP;
2317 } else {
2318 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
2321 }
2322 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002323 cur_arg++;
2324 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002325 } /* Url App Session */
2326 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002327 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002331 if (curproxy == &defproxy) {
2332 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
2335 }
2336
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 if (*(args[4]) == 0) {
2338 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2339 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002343 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 curproxy->capture_name = strdup(args[2]);
2345 curproxy->capture_namelen = strlen(curproxy->capture_name);
2346 curproxy->capture_len = atol(args[4]);
2347 if (curproxy->capture_len >= CAPTURE_LEN) {
2348 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2349 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002350 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 curproxy->capture_len = CAPTURE_LEN - 1;
2352 }
2353 curproxy->to_log |= LW_COOKIE;
2354 }
2355 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2356 struct cap_hdr *hdr;
2357
2358 if (curproxy == &defproxy) {
2359 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 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
2363
2364 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2365 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2366 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 }
2370
2371 hdr = calloc(sizeof(struct cap_hdr), 1);
2372 hdr->next = curproxy->req_cap;
2373 hdr->name = strdup(args[3]);
2374 hdr->namelen = strlen(args[3]);
2375 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002376 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 hdr->index = curproxy->nb_req_cap++;
2378 curproxy->req_cap = hdr;
2379 curproxy->to_log |= LW_REQHDR;
2380 }
2381 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2382 struct cap_hdr *hdr;
2383
2384 if (curproxy == &defproxy) {
2385 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 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 }
2389
2390 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2391 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2392 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
2396 hdr = calloc(sizeof(struct cap_hdr), 1);
2397 hdr->next = curproxy->rsp_cap;
2398 hdr->name = strdup(args[3]);
2399 hdr->namelen = strlen(args[3]);
2400 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002401 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 hdr->index = curproxy->nb_rsp_cap++;
2403 curproxy->rsp_cap = hdr;
2404 curproxy->to_log |= LW_RSPHDR;
2405 }
2406 else {
2407 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2408 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 }
2412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002414 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002416
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 if (*(args[1]) == 0) {
2418 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2419 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 }
2423 curproxy->conn_retries = atol(args[1]);
2424 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002425 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
2426 struct req_acl_rule *req_acl;
2427
2428 if (curproxy == &defproxy) {
2429 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
2432 }
2433
2434
2435 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2436 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2437 file, linenum, args[0]);
2438 err_code |= ERR_WARN;
2439 }
2440
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002441 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002442
2443 if (!req_acl) {
2444 err_code |= ERR_ALERT | ERR_ABORT;
2445 goto out;
2446 }
2447
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002448 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002449 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2450 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002451 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002452 if (curproxy == &defproxy) {
2453 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002456 }
2457
Willy Tarreauef6494c2010-01-28 17:12:36 +01002458 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002459 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002463 }
2464
Willy Tarreauef6494c2010-01-28 17:12:36 +01002465 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002466 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2467 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002470 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002471
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002472 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002473 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002474 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002475 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002476 struct redirect_rule *rule;
2477 int cur_arg;
2478 int type = REDIRECT_TYPE_NONE;
2479 int code = 302;
2480 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002481 char *cookie = NULL;
2482 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002483 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002484
Cyril Bonté99ed3272010-01-24 23:29:44 +01002485 if (curproxy == &defproxy) {
2486 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
2490
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002491 cur_arg = 1;
2492 while (*(args[cur_arg])) {
2493 if (!strcmp(args[cur_arg], "location")) {
2494 if (!*args[cur_arg + 1]) {
2495 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2496 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002499 }
2500
2501 type = REDIRECT_TYPE_LOCATION;
2502 cur_arg++;
2503 destination = args[cur_arg];
2504 }
2505 else if (!strcmp(args[cur_arg], "prefix")) {
2506 if (!*args[cur_arg + 1]) {
2507 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2508 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002511 }
2512
2513 type = REDIRECT_TYPE_PREFIX;
2514 cur_arg++;
2515 destination = args[cur_arg];
2516 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002517 else if (!strcmp(args[cur_arg], "set-cookie")) {
2518 if (!*args[cur_arg + 1]) {
2519 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2520 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002523 }
2524
2525 cur_arg++;
2526 cookie = args[cur_arg];
2527 cookie_set = 1;
2528 }
2529 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2530 if (!*args[cur_arg + 1]) {
2531 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2532 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002535 }
2536
2537 cur_arg++;
2538 cookie = args[cur_arg];
2539 cookie_set = 0;
2540 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002541 else if (!strcmp(args[cur_arg],"code")) {
2542 if (!*args[cur_arg + 1]) {
2543 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2544 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_ALERT | ERR_FATAL;
2546 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002547 }
2548 cur_arg++;
2549 code = atol(args[cur_arg]);
2550 if (code < 301 || code > 303) {
2551 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2552 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002555 }
2556 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002557 else if (!strcmp(args[cur_arg],"drop-query")) {
2558 flags |= REDIRECT_FLAG_DROP_QS;
2559 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002560 else if (!strcmp(args[cur_arg],"append-slash")) {
2561 flags |= REDIRECT_FLAG_APPEND_SLASH;
2562 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002563 else if (strcmp(args[cur_arg], "if") == 0 ||
2564 strcmp(args[cur_arg], "unless") == 0) {
2565 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2566 if (!cond) {
2567 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2568 file, linenum, args[0]);
2569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
2571 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002572 break;
2573 }
2574 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002575 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 +02002576 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002579 }
2580 cur_arg++;
2581 }
2582
2583 if (type == REDIRECT_TYPE_NONE) {
2584 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2585 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002588 }
2589
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002590 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2591 rule->cond = cond;
2592 rule->rdr_str = strdup(destination);
2593 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002594 if (cookie) {
2595 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002596 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002597 */
2598 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002599 if (cookie_set) {
2600 rule->cookie_str = malloc(rule->cookie_len + 10);
2601 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2602 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2603 rule->cookie_len += 9;
2604 } else {
2605 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002606 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002607 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2608 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002609 }
2610 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002611 rule->type = type;
2612 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002613 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002614 LIST_INIT(&rule->list);
2615 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002616 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002617 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002618 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002619 struct switching_rule *rule;
2620
Willy Tarreaub099aca2008-10-12 17:26:37 +02002621 if (curproxy == &defproxy) {
2622 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002625 }
2626
Willy Tarreau55ea7572007-06-17 19:56:27 +02002627 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002629
2630 if (*(args[1]) == 0) {
2631 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002634 }
2635
Willy Tarreauef6494c2010-01-28 17:12:36 +01002636 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002637 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2638 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002641 }
2642
Willy Tarreauef6494c2010-01-28 17:12:36 +01002643 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002644 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002645 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002646 err_code |= ERR_ALERT | ERR_FATAL;
2647 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002648 }
2649
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002650 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002651
Willy Tarreau55ea7572007-06-17 19:56:27 +02002652 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2653 rule->cond = cond;
2654 rule->be.name = strdup(args[1]);
2655 LIST_INIT(&rule->list);
2656 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2657 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002658 else if ((!strcmp(args[0], "force-persist")) ||
2659 (!strcmp(args[0], "ignore-persist"))) {
2660 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002661
2662 if (curproxy == &defproxy) {
2663 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
2668 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2669 err_code |= ERR_WARN;
2670
Willy Tarreauef6494c2010-01-28 17:12:36 +01002671 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002672 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2673 file, linenum, args[0]);
2674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
2676 }
2677
Willy Tarreauef6494c2010-01-28 17:12:36 +01002678 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002679 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2680 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
2683 }
2684
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002685 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002686
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002687 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002688 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002689 if (!strcmp(args[0], "force-persist")) {
2690 rule->type = PERSIST_TYPE_FORCE;
2691 } else {
2692 rule->type = PERSIST_TYPE_IGNORE;
2693 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002694 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002695 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002696 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002697 else if (!strcmp(args[0], "stick-table")) {
2698 int myidx = 1;
2699
Emeric Brun32da3c42010-09-23 18:39:19 +02002700 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002701 curproxy->table.type = (unsigned int)-1;
2702 while (*args[myidx]) {
2703 const char *err;
2704
2705 if (strcmp(args[myidx], "size") == 0) {
2706 myidx++;
2707 if (!*(args[myidx])) {
2708 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2709 file, linenum, args[myidx-1]);
2710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
2712 }
2713 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2714 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2715 file, linenum, *err, args[myidx-1]);
2716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
2718 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002719 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002720 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002721 else if (strcmp(args[myidx], "peers") == 0) {
2722 myidx++;
2723 if (!*(args[myidx])) {
2724 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2725 file, linenum, args[myidx-1]);
2726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
2728 }
2729 curproxy->table.peers.name = strdup(args[myidx++]);
2730 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002731 else if (strcmp(args[myidx], "expire") == 0) {
2732 myidx++;
2733 if (!*(args[myidx])) {
2734 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2735 file, linenum, args[myidx-1]);
2736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
2738 }
2739 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2740 if (err) {
2741 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2742 file, linenum, *err, args[myidx-1]);
2743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
2745 }
2746 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002747 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002748 }
2749 else if (strcmp(args[myidx], "nopurge") == 0) {
2750 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002751 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002752 }
2753 else if (strcmp(args[myidx], "type") == 0) {
2754 myidx++;
2755 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2756 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2757 file, linenum, args[myidx]);
2758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
2760 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002761 /* myidx already points to next arg */
2762 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002763 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002764 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002765 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002766
2767 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002768 nw = args[myidx];
2769 while (*nw) {
2770 /* the "store" keyword supports a comma-separated list */
2771 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002772 sa = NULL; /* store arg */
2773 while (*nw && *nw != ',') {
2774 if (*nw == '(') {
2775 *nw = 0;
2776 sa = ++nw;
2777 while (*nw != ')') {
2778 if (!*nw) {
2779 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2780 file, linenum, args[0], cw);
2781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
2783 }
2784 nw++;
2785 }
2786 *nw = '\0';
2787 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002788 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002789 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002790 if (*nw)
2791 *nw++ = '\0';
2792 type = stktable_get_data_type(cw);
2793 if (type < 0) {
2794 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2795 file, linenum, args[0], cw);
2796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
2798 }
Willy Tarreauac782882010-06-20 10:41:54 +02002799
2800 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2801 switch (err) {
2802 case PE_NONE: break;
2803 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002804 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2805 file, linenum, args[0], cw);
2806 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002807 break;
2808
2809 case PE_ARG_MISSING:
2810 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2811 file, linenum, args[0], cw);
2812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
2814
2815 case PE_ARG_NOT_USED:
2816 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2817 file, linenum, args[0], cw);
2818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
2820
2821 default:
2822 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2823 file, linenum, args[0], cw);
2824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002826 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002827 }
2828 myidx++;
2829 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002830 else {
2831 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2832 file, linenum, args[myidx]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002835 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002836 }
2837
2838 if (!curproxy->table.size) {
2839 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2840 file, linenum);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843 }
2844
2845 if (curproxy->table.type == (unsigned int)-1) {
2846 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2847 file, linenum);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
2851 }
2852 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002853 struct sticking_rule *rule;
2854 struct pattern_expr *expr;
2855 int myidx = 0;
2856 const char *name = NULL;
2857 int flags;
2858
2859 if (curproxy == &defproxy) {
2860 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
2864
2865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2866 err_code |= ERR_WARN;
2867 goto out;
2868 }
2869
2870 myidx++;
2871 if ((strcmp(args[myidx], "store") == 0) ||
2872 (strcmp(args[myidx], "store-request") == 0)) {
2873 myidx++;
2874 flags = STK_IS_STORE;
2875 }
2876 else if (strcmp(args[myidx], "store-response") == 0) {
2877 myidx++;
2878 flags = STK_IS_STORE | STK_ON_RSP;
2879 }
2880 else if (strcmp(args[myidx], "match") == 0) {
2881 myidx++;
2882 flags = STK_IS_MATCH;
2883 }
2884 else if (strcmp(args[myidx], "on") == 0) {
2885 myidx++;
2886 flags = STK_IS_MATCH | STK_IS_STORE;
2887 }
2888 else {
2889 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892 }
2893
2894 if (*(args[myidx]) == 0) {
2895 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
2898 }
2899
Emeric Brun485479d2010-09-23 18:02:19 +02002900 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002901 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002902 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
2905 }
2906
2907 if (flags & STK_ON_RSP) {
2908 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2909 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2910 file, linenum, args[0], expr->fetch->kw);
2911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
2913 }
2914 } else {
2915 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2916 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2917 file, linenum, args[0], expr->fetch->kw);
2918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
2920 }
2921 }
2922
2923 if (strcmp(args[myidx], "table") == 0) {
2924 myidx++;
2925 name = args[myidx++];
2926 }
2927
Willy Tarreauef6494c2010-01-28 17:12:36 +01002928 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2929 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002930 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2931 file, linenum, args[0]);
2932 err_code |= ERR_ALERT | ERR_FATAL;
2933 goto out;
2934 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002935 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002936 else if (*(args[myidx])) {
2937 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2938 file, linenum, args[0], args[myidx]);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941 }
Emeric Brun97679e72010-09-23 17:56:44 +02002942 if (flags & STK_ON_RSP)
2943 err_code |= warnif_cond_requires_req(cond, file, linenum);
2944 else
2945 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002946
Emeric Brunb982a3d2010-01-04 15:45:53 +01002947 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2948 rule->cond = cond;
2949 rule->expr = expr;
2950 rule->flags = flags;
2951 rule->table.name = name ? strdup(name) : NULL;
2952 LIST_INIT(&rule->list);
2953 if (flags & STK_ON_RSP)
2954 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2955 else
2956 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002959 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002960 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002961
Willy Tarreaubaaee002006-06-26 02:48:02 +02002962 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2963 curproxy->uri_auth = NULL; /* we must detach from the default config */
2964
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002965 if (!*args[1]) {
2966 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002967 } else if (!strcmp(args[1], "admin")) {
2968 struct stats_admin_rule *rule;
2969
2970 if (curproxy == &defproxy) {
2971 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
2975
2976 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2977 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2978 err_code |= ERR_ALERT | ERR_ABORT;
2979 goto out;
2980 }
2981
2982 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2983 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2984 file, linenum, args[0], args[1]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2989 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2990 file, linenum, args[0], args[1]);
2991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
2993 }
2994
2995 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2996
2997 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2998 rule->cond = cond;
2999 LIST_INIT(&rule->list);
3000 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 } else if (!strcmp(args[1], "uri")) {
3002 if (*(args[2]) == 0) {
3003 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003006 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3007 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_ALERT | ERR_ABORT;
3009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 }
3011 } else if (!strcmp(args[1], "realm")) {
3012 if (*(args[2]) == 0) {
3013 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3017 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_ABORT;
3019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003021 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003022 unsigned interval;
3023
3024 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3025 if (err) {
3026 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3027 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003030 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3031 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003032 err_code |= ERR_ALERT | ERR_ABORT;
3033 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003034 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003035 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
3036 struct req_acl_rule *req_acl;
3037
3038 if (curproxy == &defproxy) {
3039 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
3042 }
3043
3044 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3045 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3046 err_code |= ERR_ALERT | ERR_ABORT;
3047 goto out;
3048 }
3049
3050 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
3051 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
3052 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3053 file, linenum, args[0]);
3054 err_code |= ERR_WARN;
3055 }
3056
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003057 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003058
3059 if (!req_acl) {
3060 err_code |= ERR_ALERT | ERR_ABORT;
3061 goto out;
3062 }
3063
Willy Tarreau9cc670f2010-02-01 10:43:44 +01003064 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003065 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
3066
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 } else if (!strcmp(args[1], "auth")) {
3068 if (*(args[2]) == 0) {
3069 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3073 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_ALERT | ERR_ABORT;
3075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 }
3077 } else if (!strcmp(args[1], "scope")) {
3078 if (*(args[2]) == 0) {
3079 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3083 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_ABORT;
3085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 }
3087 } else if (!strcmp(args[1], "enable")) {
3088 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3089 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003090 err_code |= ERR_ALERT | ERR_ABORT;
3091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003093 } else if (!strcmp(args[1], "hide-version")) {
3094 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3095 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003096 err_code |= ERR_ALERT | ERR_ABORT;
3097 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003098 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003099 } else if (!strcmp(args[1], "show-legends")) {
3100 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3101 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3102 err_code |= ERR_ALERT | ERR_ABORT;
3103 goto out;
3104 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003105 } else if (!strcmp(args[1], "show-node")) {
3106
3107 if (*args[2]) {
3108 int i;
3109 char c;
3110
3111 for (i=0; args[2][i]; i++) {
3112 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003113 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3114 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003115 break;
3116 }
3117
3118 if (!i || args[2][i]) {
3119 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3120 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3121 file, linenum, args[0], args[1]);
3122 err_code |= ERR_ALERT | ERR_FATAL;
3123 goto out;
3124 }
3125 }
3126
3127 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3128 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3129 err_code |= ERR_ALERT | ERR_ABORT;
3130 goto out;
3131 }
3132 } else if (!strcmp(args[1], "show-desc")) {
3133 char *desc = NULL;
3134
3135 if (*args[2]) {
3136 int i, len=0;
3137 char *d;
3138
3139 for(i=2; *args[i]; i++)
3140 len += strlen(args[i])+1;
3141
3142 desc = d = (char *)calloc(1, len);
3143
3144 d += sprintf(d, "%s", args[2]);
3145 for(i=3; *args[i]; i++)
3146 d += sprintf(d, " %s", args[i]);
3147 }
3148
3149 if (!*args[2] && !global.desc)
3150 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3151 file, linenum, args[1]);
3152 else {
3153 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3154 free(desc);
3155 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3156 err_code |= ERR_ALERT | ERR_ABORT;
3157 goto out;
3158 }
3159 free(desc);
3160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003162stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003163 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 +01003164 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 }
3168 }
3169 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003170 int optnum;
3171
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003172 if (*(args[1]) == '\0') {
3173 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003178
3179 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3180 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003181 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3182 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3183 file, linenum, cfg_opts[optnum].name);
3184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
3186 }
Willy Tarreau93893792009-07-23 13:19:11 +02003187 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3188 err_code |= ERR_WARN;
3189 goto out;
3190 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003191
Willy Tarreau3842f002009-06-14 11:39:52 +02003192 curproxy->no_options &= ~cfg_opts[optnum].val;
3193 curproxy->options &= ~cfg_opts[optnum].val;
3194
3195 switch (kwm) {
3196 case KWM_STD:
3197 curproxy->options |= cfg_opts[optnum].val;
3198 break;
3199 case KWM_NO:
3200 curproxy->no_options |= cfg_opts[optnum].val;
3201 break;
3202 case KWM_DEF: /* already cleared */
3203 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003204 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003205
Willy Tarreau93893792009-07-23 13:19:11 +02003206 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003207 }
3208 }
3209
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003210 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3211 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003212 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3213 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3214 file, linenum, cfg_opts2[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_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3219 err_code |= ERR_WARN;
3220 goto out;
3221 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003222
Willy Tarreau3842f002009-06-14 11:39:52 +02003223 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3224 curproxy->options2 &= ~cfg_opts2[optnum].val;
3225
3226 switch (kwm) {
3227 case KWM_STD:
3228 curproxy->options2 |= cfg_opts2[optnum].val;
3229 break;
3230 case KWM_NO:
3231 curproxy->no_options2 |= cfg_opts2[optnum].val;
3232 break;
3233 case KWM_DEF: /* already cleared */
3234 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003235 }
Willy Tarreau93893792009-07-23 13:19:11 +02003236 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003237 }
3238 }
3239
Willy Tarreau3842f002009-06-14 11:39:52 +02003240 if (kwm != KWM_STD) {
3241 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003242 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003245 }
3246
Emeric Brun3a058f32009-06-30 18:26:00 +02003247 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003248 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003249 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003251 if (*(args[2]) != '\0') {
3252 if (!strcmp(args[2], "clf")) {
3253 curproxy->options2 |= PR_O2_CLFLOG;
3254 } else {
3255 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003258 }
3259 }
3260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 else if (!strcmp(args[1], "tcplog"))
3262 /* generate a detailed TCP log */
3263 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 else if (!strcmp(args[1], "tcpka")) {
3265 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003266 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003268
3269 if (curproxy->cap & PR_CAP_FE)
3270 curproxy->options |= PR_O_TCP_CLI_KA;
3271 if (curproxy->cap & PR_CAP_BE)
3272 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 }
3274 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003275 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_WARN;
3277
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003279 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003280 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003281 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003282 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003283 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003284 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003285 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 if (!*args[2]) { /* no argument */
3287 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3288 curproxy->check_len = strlen(DEF_CHECK_REQ);
3289 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003290 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 curproxy->check_req = (char *)malloc(reqlen);
3292 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003293 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003295 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 if (*args[4])
3297 reqlen += strlen(args[4]);
3298 else
3299 reqlen += strlen("HTTP/1.0");
3300
3301 curproxy->check_req = (char *)malloc(reqlen);
3302 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003303 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003305 }
3306 else if (!strcmp(args[1], "ssl-hello-chk")) {
3307 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003308 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003310
Willy Tarreaua534fea2008-08-03 12:19:50 +02003311 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003312 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003313 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003314 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003315 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003316 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003317 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
Willy Tarreau23677902007-05-08 23:50:35 +02003319 else if (!strcmp(args[1], "smtpchk")) {
3320 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003321 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003322 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003323 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003324 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003325 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003326 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003327 curproxy->options |= PR_O_SMTP_CHK;
3328
3329 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3330 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3331 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3332 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3333 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3334 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3335 curproxy->check_req = (char *)malloc(reqlen);
3336 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3337 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3338 } else {
3339 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3340 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3341 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3342 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3343 }
3344 }
3345 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003346 else if (!strcmp(args[1], "mysql-check")) {
3347 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003348 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3349 err_code |= ERR_WARN;
3350
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003351 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003352 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003353 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003354 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003355 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003356 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003357 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003358
3359 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3360 * const char mysql40_client_auth_pkt[] = {
3361 * "\x0e\x00\x00" // packet length
3362 * "\x01" // packet number
3363 * "\x00\x00" // client capabilities
3364 * "\x00\x00\x01" // max packet
3365 * "haproxy\x00" // username (null terminated string)
3366 * "\x00" // filler (always 0x00)
3367 * "\x01\x00\x00" // packet length
3368 * "\x00" // packet number
3369 * "\x01" // COM_QUIT command
3370 * };
3371 */
3372
3373 if (*(args[2])) {
3374 int cur_arg = 2;
3375
3376 while (*(args[cur_arg])) {
3377 if (strcmp(args[cur_arg], "user") == 0) {
3378 char *mysqluser;
3379 int packetlen, reqlen, userlen;
3380
3381 /* suboption header - needs additional argument for it */
3382 if (*(args[cur_arg+1]) == 0) {
3383 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3384 file, linenum, args[0], args[1], args[cur_arg]);
3385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
3387 }
3388 mysqluser = args[cur_arg + 1];
3389 userlen = strlen(mysqluser);
3390 packetlen = userlen + 7;
3391 reqlen = packetlen + 9;
3392
3393 free(curproxy->check_req);
3394 curproxy->check_req = (char *)calloc(1, reqlen);
3395 curproxy->check_len = reqlen;
3396
3397 snprintf(curproxy->check_req, 4, "%c%c%c",
3398 ((unsigned char) packetlen & 0xff),
3399 ((unsigned char) (packetlen >> 8) & 0xff),
3400 ((unsigned char) (packetlen >> 16) & 0xff));
3401
3402 curproxy->check_req[3] = 1;
3403 curproxy->check_req[8] = 1;
3404 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3405 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3406 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3407 cur_arg += 2;
3408 } else {
3409 /* unknown suboption - catchall */
3410 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3411 file, linenum, args[0], args[1]);
3412 err_code |= ERR_ALERT | ERR_FATAL;
3413 goto out;
3414 }
3415 } /* end while loop */
3416 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003417 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003418 else if (!strcmp(args[1], "ldap-check")) {
3419 /* use LDAP request to check servers' health */
3420 free(curproxy->check_req);
3421 curproxy->check_req = NULL;
3422 curproxy->options &= ~PR_O_HTTP_CHK;
3423 curproxy->options &= ~PR_O_SMTP_CHK;
3424 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3425 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3426 curproxy->options2 |= PR_O2_LDAP_CHK;
3427
3428 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3429 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3430 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3431 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003432 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003433 int cur_arg;
3434
3435 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3436 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003437 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003438
3439 curproxy->options |= PR_O_FWDFOR;
3440
3441 free(curproxy->fwdfor_hdr_name);
3442 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3443 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3444
3445 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3446 cur_arg = 2;
3447 while (*(args[cur_arg])) {
3448 if (!strcmp(args[cur_arg], "except")) {
3449 /* suboption except - needs additional argument for it */
3450 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3451 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3452 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003455 }
3456 /* flush useless bits */
3457 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003458 cur_arg += 2;
3459 } else if (!strcmp(args[cur_arg], "header")) {
3460 /* suboption header - needs additional argument for it */
3461 if (*(args[cur_arg+1]) == 0) {
3462 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3463 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003466 }
3467 free(curproxy->fwdfor_hdr_name);
3468 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3469 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3470 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003471 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003472 /* unknown suboption - catchall */
3473 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3474 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003477 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003478 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003479 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003480 else if (!strcmp(args[1], "originalto")) {
3481 int cur_arg;
3482
3483 /* insert x-original-to field, but not for the IP address listed as an except.
3484 * set default options (ie: bitfield, header name, etc)
3485 */
3486
3487 curproxy->options |= PR_O_ORGTO;
3488
3489 free(curproxy->orgto_hdr_name);
3490 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3491 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3492
3493 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3494 cur_arg = 2;
3495 while (*(args[cur_arg])) {
3496 if (!strcmp(args[cur_arg], "except")) {
3497 /* suboption except - needs additional argument for it */
3498 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3499 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3500 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003503 }
3504 /* flush useless bits */
3505 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3506 cur_arg += 2;
3507 } else if (!strcmp(args[cur_arg], "header")) {
3508 /* suboption header - needs additional argument for it */
3509 if (*(args[cur_arg+1]) == 0) {
3510 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3511 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003514 }
3515 free(curproxy->orgto_hdr_name);
3516 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3517 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3518 cur_arg += 2;
3519 } else {
3520 /* unknown suboption - catchall */
3521 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3522 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003525 }
3526 } /* end while loop */
3527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 else {
3529 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 }
Willy Tarreau93893792009-07-23 13:19:11 +02003533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003535 else if (!strcmp(args[0], "default_backend")) {
3536 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003538
3539 if (*(args[1]) == 0) {
3540 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003543 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003544 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003545 curproxy->defbe.name = strdup(args[1]);
3546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003548 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003550
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003551 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 /* enable reconnections to dispatch */
3555 curproxy->options |= PR_O_REDISP;
3556 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003557 else if (!strcmp(args[0], "http-check")) {
3558 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003560
3561 if (strcmp(args[1], "disable-on-404") == 0) {
3562 /* enable a graceful server shutdown on an HTTP 404 response */
3563 curproxy->options |= PR_O_DISABLE404;
3564 }
Willy Tarreauef781042010-01-27 11:53:01 +01003565 else if (strcmp(args[1], "send-state") == 0) {
3566 /* enable emission of the apparent state of a server in HTTP checks */
3567 curproxy->options2 |= PR_O2_CHK_SNDST;
3568 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003569 else if (strcmp(args[1], "expect") == 0) {
3570 const char *ptr_arg;
3571 int cur_arg;
3572
3573 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3574 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577 }
3578
3579 cur_arg = 2;
3580 /* consider exclamation marks, sole or at the beginning of a word */
3581 while (*(ptr_arg = args[cur_arg])) {
3582 while (*ptr_arg == '!') {
3583 curproxy->options2 ^= PR_O2_EXP_INV;
3584 ptr_arg++;
3585 }
3586 if (*ptr_arg)
3587 break;
3588 cur_arg++;
3589 }
3590 /* now ptr_arg points to the beginning of a word past any possible
3591 * exclamation mark, and cur_arg is the argument which holds this word.
3592 */
3593 if (strcmp(ptr_arg, "status") == 0) {
3594 if (!*(args[cur_arg + 1])) {
3595 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3596 file, linenum, args[0], args[1], ptr_arg);
3597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
3599 }
3600 curproxy->options2 |= PR_O2_EXP_STS;
3601 curproxy->expect_str = strdup(args[cur_arg + 1]);
3602 }
3603 else if (strcmp(ptr_arg, "string") == 0) {
3604 if (!*(args[cur_arg + 1])) {
3605 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3606 file, linenum, args[0], args[1], ptr_arg);
3607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
3609 }
3610 curproxy->options2 |= PR_O2_EXP_STR;
3611 curproxy->expect_str = strdup(args[cur_arg + 1]);
3612 }
3613 else if (strcmp(ptr_arg, "rstatus") == 0) {
3614 if (!*(args[cur_arg + 1])) {
3615 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3616 file, linenum, args[0], args[1], ptr_arg);
3617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
3619 }
3620 curproxy->options2 |= PR_O2_EXP_RSTS;
3621 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3622 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3623 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3624 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
3627 }
3628 }
3629 else if (strcmp(ptr_arg, "rstring") == 0) {
3630 if (!*(args[cur_arg + 1])) {
3631 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3632 file, linenum, args[0], args[1], ptr_arg);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636 curproxy->options2 |= PR_O2_EXP_RSTR;
3637 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3638 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3639 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3640 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
3643 }
3644 }
3645 else {
3646 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3647 file, linenum, args[0], args[1], ptr_arg);
3648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
3650 }
3651 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003652 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003653 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003656 }
3657 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003658 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003659 if (curproxy == &defproxy) {
3660 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003663 }
3664
Willy Tarreaub80c2302007-11-30 20:51:32 +01003665 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003667
3668 if (strcmp(args[1], "fail") == 0) {
3669 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003670 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003671 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3672 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003675 }
3676
Willy Tarreauef6494c2010-01-28 17:12:36 +01003677 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003678 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3679 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003682 }
3683 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3684 }
3685 else {
3686 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003689 }
3690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691#ifdef TPROXY
3692 else if (!strcmp(args[0], "transparent")) {
3693 /* enable transparent proxy connections */
3694 curproxy->options |= PR_O_TRANSP;
3695 }
3696#endif
3697 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003698 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003700
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 if (*(args[1]) == 0) {
3702 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 }
3706 curproxy->maxconn = atol(args[1]);
3707 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003708 else if (!strcmp(args[0], "backlog")) { /* backlog */
3709 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003711
3712 if (*(args[1]) == 0) {
3713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003716 }
3717 curproxy->backlog = atol(args[1]);
3718 }
Willy Tarreau86034312006-12-29 00:10:33 +01003719 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003720 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003722
Willy Tarreau86034312006-12-29 00:10:33 +01003723 if (*(args[1]) == 0) {
3724 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003727 }
3728 curproxy->fullconn = atol(args[1]);
3729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3731 if (*(args[1]) == 0) {
3732 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003736 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3737 if (err) {
3738 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3739 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003742 }
3743 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744 }
3745 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003746 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 if (curproxy == &defproxy) {
3748 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003752 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003754
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 if (strchr(args[1], ':') == NULL) {
3756 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003759 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003760 sk = str2sa(args[1]);
3761 if (!sk) {
3762 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
3765 }
3766 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 }
3768 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003769 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003771
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003772 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003773 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3774 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003777 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003779 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3780 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3781 err_code |= ERR_WARN;
3782
3783 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3784 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3785 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3786 }
3787 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3788 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3789 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3790 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003791 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3792 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3793 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3794 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003795 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003796 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003797 err_code |= ERR_ALERT | ERR_FATAL;
3798 goto out;
3799 }
3800 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003801 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003802 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003803 char *rport, *raddr;
3804 short realport = 0;
3805 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003807 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003812 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814
3815 if (!*args[2]) {
3816 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3817 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003821
3822 err = invalid_char(args[1]);
3823 if (err) {
3824 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3825 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_ALERT | ERR_FATAL;
3827 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003828 }
3829
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003830 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003831 struct sockaddr_in *sk;
3832
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003833 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3834 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3835 err_code |= ERR_ALERT | ERR_ABORT;
3836 goto out;
3837 }
3838
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003839 /* the servers are linked backwards first */
3840 newsrv->next = curproxy->srv;
3841 curproxy->srv = newsrv;
3842 newsrv->proxy = curproxy;
3843 newsrv->conf.file = file;
3844 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003846 LIST_INIT(&newsrv->pendconns);
3847 do_check = 0;
3848 newsrv->state = SRV_RUNNING; /* early server setup */
3849 newsrv->last_change = now.tv_sec;
3850 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003852 /* several ways to check the port component :
3853 * - IP => port=+0, relative
3854 * - IP: => port=+0, relative
3855 * - IP:N => port=N, absolute
3856 * - IP:+N => port=+N, relative
3857 * - IP:-N => port=-N, relative
3858 */
3859 raddr = strdup(args[2]);
3860 rport = strchr(raddr, ':');
3861 if (rport) {
3862 *rport++ = 0;
3863 realport = atol(rport);
3864 if (!isdigit((unsigned char)*rport))
3865 newsrv->state |= SRV_MAPPORTS;
3866 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003868
Willy Tarreaud5191e72010-02-09 20:50:45 +01003869 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003870 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003871 if (!sk) {
3872 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
3875 }
3876 newsrv->addr = *sk;
3877 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003878
3879 newsrv->check_port = curproxy->defsrv.check_port;
3880 newsrv->inter = curproxy->defsrv.inter;
3881 newsrv->fastinter = curproxy->defsrv.fastinter;
3882 newsrv->downinter = curproxy->defsrv.downinter;
3883 newsrv->rise = curproxy->defsrv.rise;
3884 newsrv->fall = curproxy->defsrv.fall;
3885 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3886 newsrv->minconn = curproxy->defsrv.minconn;
3887 newsrv->maxconn = curproxy->defsrv.maxconn;
3888 newsrv->slowstart = curproxy->defsrv.slowstart;
3889 newsrv->onerror = curproxy->defsrv.onerror;
3890 newsrv->consecutive_errors_limit
3891 = curproxy->defsrv.consecutive_errors_limit;
3892 newsrv->uweight = newsrv->iweight
3893 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003895 newsrv->curfd = -1; /* no health-check in progress */
3896 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003898 cur_arg = 3;
3899 } else {
3900 newsrv = &curproxy->defsrv;
3901 cur_arg = 1;
3902 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003903
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003905 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003906 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003907
3908 if (!*args[cur_arg + 1]) {
3909 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3910 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003913 }
3914
3915 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003916 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003917
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003918 if (newsrv->puid <= 0) {
3919 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003920 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003923 }
3924
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003925 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3926 if (node) {
3927 struct server *target = container_of(node, struct server, conf.id);
3928 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3929 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
3932 }
3933 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003934 cur_arg += 2;
3935 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003936 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003937 newsrv->cookie = strdup(args[cur_arg + 1]);
3938 newsrv->cklen = strlen(args[cur_arg + 1]);
3939 cur_arg += 2;
3940 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003941 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003942 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3943 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3944 cur_arg += 2;
3945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003947 if (!*args[cur_arg + 1]) {
3948 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3949 file, linenum, args[cur_arg]);
3950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
3952 }
3953
Willy Tarreaubaaee002006-06-26 02:48:02 +02003954 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003955 if (newsrv->rise <= 0) {
3956 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3957 file, linenum, args[cur_arg]);
3958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
3960 }
3961
Willy Tarreau96839092010-03-29 10:02:24 +02003962 if (newsrv->health)
3963 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 cur_arg += 2;
3965 }
3966 else if (!strcmp(args[cur_arg], "fall")) {
3967 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003968
3969 if (!*args[cur_arg + 1]) {
3970 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3971 file, linenum, args[cur_arg]);
3972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
3974 }
3975
3976 if (newsrv->fall <= 0) {
3977 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3978 file, linenum, args[cur_arg]);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
3982
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983 cur_arg += 2;
3984 }
3985 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003986 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3987 if (err) {
3988 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3989 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003992 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003993 if (val <= 0) {
3994 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3995 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003998 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003999 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004000 cur_arg += 2;
4001 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004002 else if (!strcmp(args[cur_arg], "fastinter")) {
4003 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4004 if (err) {
4005 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4006 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004009 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004010 if (val <= 0) {
4011 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4012 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004015 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004016 newsrv->fastinter = val;
4017 cur_arg += 2;
4018 }
4019 else if (!strcmp(args[cur_arg], "downinter")) {
4020 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4021 if (err) {
4022 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4023 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004026 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004027 if (val <= 0) {
4028 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4029 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004032 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004033 newsrv->downinter = val;
4034 cur_arg += 2;
4035 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004036 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004037 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4038 if (!sk) {
4039 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042 }
4043 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004044 cur_arg += 2;
4045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 else if (!strcmp(args[cur_arg], "port")) {
4047 newsrv->check_port = atol(args[cur_arg + 1]);
4048 cur_arg += 2;
4049 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004050 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 newsrv->state |= SRV_BACKUP;
4052 cur_arg ++;
4053 }
4054 else if (!strcmp(args[cur_arg], "weight")) {
4055 int w;
4056 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004057 if (w < 0 || w > 256) {
4058 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004063 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 cur_arg += 2;
4065 }
4066 else if (!strcmp(args[cur_arg], "minconn")) {
4067 newsrv->minconn = atol(args[cur_arg + 1]);
4068 cur_arg += 2;
4069 }
4070 else if (!strcmp(args[cur_arg], "maxconn")) {
4071 newsrv->maxconn = atol(args[cur_arg + 1]);
4072 cur_arg += 2;
4073 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004074 else if (!strcmp(args[cur_arg], "maxqueue")) {
4075 newsrv->maxqueue = atol(args[cur_arg + 1]);
4076 cur_arg += 2;
4077 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004078 else if (!strcmp(args[cur_arg], "slowstart")) {
4079 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004080 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004081 if (err) {
4082 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4083 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004086 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004087 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004088 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4089 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004092 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004093 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004094 cur_arg += 2;
4095 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004096 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004097
4098 if (!*args[cur_arg + 1]) {
4099 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4100 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004103 }
4104
4105 newsrv->trackit = strdup(args[cur_arg + 1]);
4106
4107 cur_arg += 2;
4108 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004109 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004110 global.maxsock++;
4111 do_check = 1;
4112 cur_arg += 1;
4113 }
Willy Tarreau96839092010-03-29 10:02:24 +02004114 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4115 newsrv->state |= SRV_MAINTAIN;
4116 newsrv->state &= ~SRV_RUNNING;
4117 newsrv->health = 0;
4118 cur_arg += 1;
4119 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004120 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004121 if (!strcmp(args[cur_arg + 1], "none"))
4122 newsrv->observe = HANA_OBS_NONE;
4123 else if (!strcmp(args[cur_arg + 1], "layer4"))
4124 newsrv->observe = HANA_OBS_LAYER4;
4125 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4126 if (curproxy->mode != PR_MODE_HTTP) {
4127 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4128 file, linenum, args[cur_arg + 1]);
4129 err_code |= ERR_ALERT;
4130 }
4131 newsrv->observe = HANA_OBS_LAYER7;
4132 }
4133 else {
4134 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004135 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004136 file, linenum, args[cur_arg], args[cur_arg + 1]);
4137 err_code |= ERR_ALERT | ERR_FATAL;
4138 goto out;
4139 }
4140
4141 cur_arg += 2;
4142 }
4143 else if (!strcmp(args[cur_arg], "on-error")) {
4144 if (!strcmp(args[cur_arg + 1], "fastinter"))
4145 newsrv->onerror = HANA_ONERR_FASTINTER;
4146 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4147 newsrv->onerror = HANA_ONERR_FAILCHK;
4148 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4149 newsrv->onerror = HANA_ONERR_SUDDTH;
4150 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4151 newsrv->onerror = HANA_ONERR_MARKDWN;
4152 else {
4153 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004154 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004155 file, linenum, args[cur_arg], args[cur_arg + 1]);
4156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
4158 }
4159
4160 cur_arg += 2;
4161 }
4162 else if (!strcmp(args[cur_arg], "error-limit")) {
4163 if (!*args[cur_arg + 1]) {
4164 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4165 file, linenum, args[cur_arg]);
4166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
4168 }
4169
4170 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4171
4172 if (newsrv->consecutive_errors_limit <= 0) {
4173 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4174 file, linenum, args[cur_arg]);
4175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
4177 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004178 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004179 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004180 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004181 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004182 struct sockaddr_in *sk;
4183
Willy Tarreaubaaee002006-06-26 02:48:02 +02004184 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004185#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004186 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004187 file, linenum, "source", "usesrc");
4188#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004189 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004191#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004194 }
4195 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004196 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4197 if (!sk) {
4198 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
4201 }
4202 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004203
4204 if (port_low != port_high) {
4205 int i;
4206 if (port_low <= 0 || port_low > 65535 ||
4207 port_high <= 0 || port_high > 65535 ||
4208 port_low > port_high) {
4209 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4210 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004213 }
4214 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4215 for (i = 0; i < newsrv->sport_range->size; i++)
4216 newsrv->sport_range->ports[i] = port_low + i;
4217 }
4218
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004220 while (*(args[cur_arg])) {
4221 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004222#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4223#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004224 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4225 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4226 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004229 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004230#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004231 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004232 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004233 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004236 }
4237 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004238 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004239 newsrv->state |= SRV_TPROXY_CLI;
4240 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004241 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004242 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004243 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4244 char *name, *end;
4245
4246 name = args[cur_arg+1] + 7;
4247 while (isspace(*name))
4248 name++;
4249
4250 end = name;
4251 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4252 end++;
4253
4254 newsrv->state &= ~SRV_TPROXY_MASK;
4255 newsrv->state |= SRV_TPROXY_DYN;
4256 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4257 newsrv->bind_hdr_len = end - name;
4258 memcpy(newsrv->bind_hdr_name, name, end - name);
4259 newsrv->bind_hdr_name[end-name] = '\0';
4260 newsrv->bind_hdr_occ = -1;
4261
4262 /* now look for an occurrence number */
4263 while (isspace(*end))
4264 end++;
4265 if (*end == ',') {
4266 end++;
4267 name = end;
4268 if (*end == '-')
4269 end++;
4270 while (isdigit(*end))
4271 end++;
4272 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4273 }
4274
4275 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4276 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4277 " occurrences values smaller than %d.\n",
4278 file, linenum, MAX_HDR_HISTORY);
4279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
4281 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004282 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004283 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4284 if (!sk) {
4285 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
4288 }
4289 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004290 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004291 }
4292 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004293#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004294 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004295#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004296 cur_arg += 2;
4297 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004298#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004299 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004300 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004303#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4304 } /* "usesrc" */
4305
4306 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4307#ifdef SO_BINDTODEVICE
4308 if (!*args[cur_arg + 1]) {
4309 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4310 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004311 err_code |= ERR_ALERT | ERR_FATAL;
4312 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004313 }
4314 if (newsrv->iface_name)
4315 free(newsrv->iface_name);
4316
4317 newsrv->iface_name = strdup(args[cur_arg + 1]);
4318 newsrv->iface_len = strlen(newsrv->iface_name);
4319 global.last_checks |= LSTCHK_NETADM;
4320#else
4321 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4322 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004325#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004326 cur_arg += 2;
4327 continue;
4328 }
4329 /* this keyword in not an option of "source" */
4330 break;
4331 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004333 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004334 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4335 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004338 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004340 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004341 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 +01004342 file, linenum, newsrv->id);
4343 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004344 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 +01004345 file, linenum);
4346
Willy Tarreau93893792009-07-23 13:19:11 +02004347 err_code |= ERR_ALERT | ERR_FATAL;
4348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349 }
4350 }
4351
4352 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004353 if (newsrv->trackit) {
4354 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4355 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004356 err_code |= ERR_ALERT | ERR_FATAL;
4357 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004358 }
4359
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004360 if (!newsrv->check_port && newsrv->check_addr.sin_port)
4361 newsrv->check_port = newsrv->check_addr.sin_port;
4362
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4364 newsrv->check_port = realport; /* by default */
4365 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004366 /* not yet valid, because no port was set on
4367 * the server either. We'll check if we have
4368 * a known port on the first listener.
4369 */
4370 struct listener *l;
4371 l = curproxy->listen;
4372 if (l) {
4373 int port;
4374 port = (l->addr.ss_family == AF_INET6)
4375 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4376 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4377 newsrv->check_port = port;
4378 }
4379 }
4380 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004381 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4382 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004385 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004386
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004387 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004388 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004389 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4390 err_code |= ERR_ALERT | ERR_ABORT;
4391 goto out;
4392 }
4393
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004394 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 newsrv->state |= SRV_CHECKED;
4396 }
4397
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004398 if (!defsrv) {
4399 if (newsrv->state & SRV_BACKUP)
4400 curproxy->srv_bck++;
4401 else
4402 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004403
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004404 newsrv->prev_state = newsrv->state;
4405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004406 }
4407 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004408 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004409 int facility;
4410
4411 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4412 curproxy->logfac1 = global.logfac1;
4413 curproxy->logsrv1 = global.logsrv1;
4414 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004415 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 curproxy->logfac2 = global.logfac2;
4417 curproxy->logsrv2 = global.logsrv2;
4418 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004419 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004420 }
4421 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004422 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423
4424 facility = get_log_facility(args[2]);
4425 if (facility < 0) {
4426 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4427 exit(1);
4428 }
4429
4430 level = 7; /* max syslog level = debug */
4431 if (*(args[3])) {
4432 level = get_log_level(args[3]);
4433 if (level < 0) {
4434 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4435 exit(1);
4436 }
4437 }
4438
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004439 minlvl = 0; /* limit syslog level to this level (emerg) */
4440 if (*(args[4])) {
4441 minlvl = get_log_level(args[4]);
4442 if (level < 0) {
4443 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4444 exit(1);
4445 }
4446 }
4447
Robert Tsai81ae1952007-12-05 10:47:29 +01004448 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004449 struct sockaddr_un *sk = str2sun(args[1]);
4450 if (!sk) {
4451 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4452 args[1], (int)sizeof(sk->sun_path) - 1);
4453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 }
4456 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004457 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004458 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004459 struct sockaddr_in *sk = str2sa(args[1]);
4460 if (!sk) {
4461 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4462 err_code |= ERR_ALERT | ERR_FATAL;
4463 goto out;
4464 }
4465 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004466 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004467 if (!logsrv.u.in.sin_port) {
4468 logsrv.u.in.sin_port =
4469 htons(SYSLOG_PORT);
4470 }
4471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004472
4473 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004474 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 curproxy->logfac1 = facility;
4476 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004477 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004478 }
4479 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004480 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 curproxy->logfac2 = facility;
4482 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004483 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 }
4485 else {
4486 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 }
4490 }
4491 else {
4492 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4493 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004496 }
4497 }
4498 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004499 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004500 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004501
Willy Tarreau977b8e42006-12-29 14:19:17 +01004502 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004504
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004506 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4507 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004508 err_code |= ERR_ALERT | ERR_FATAL;
4509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004511
4512 /* we must first clear any optional default setting */
4513 curproxy->options &= ~PR_O_TPXY_MASK;
4514 free(curproxy->iface_name);
4515 curproxy->iface_name = NULL;
4516 curproxy->iface_len = 0;
4517
Willy Tarreaud5191e72010-02-09 20:50:45 +01004518 sk = str2sa(args[1]);
4519 if (!sk) {
4520 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
4523 }
4524 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004525 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004526
4527 cur_arg = 2;
4528 while (*(args[cur_arg])) {
4529 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004530#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4531#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004532 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4533 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4534 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004537 }
4538#endif
4539 if (!*args[cur_arg + 1]) {
4540 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4541 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004544 }
4545
4546 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004547 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004548 curproxy->options |= PR_O_TPXY_CLI;
4549 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004550 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004551 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004552 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4553 char *name, *end;
4554
4555 name = args[cur_arg+1] + 7;
4556 while (isspace(*name))
4557 name++;
4558
4559 end = name;
4560 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4561 end++;
4562
4563 curproxy->options &= ~PR_O_TPXY_MASK;
4564 curproxy->options |= PR_O_TPXY_DYN;
4565 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4566 curproxy->bind_hdr_len = end - name;
4567 memcpy(curproxy->bind_hdr_name, name, end - name);
4568 curproxy->bind_hdr_name[end-name] = '\0';
4569 curproxy->bind_hdr_occ = -1;
4570
4571 /* now look for an occurrence number */
4572 while (isspace(*end))
4573 end++;
4574 if (*end == ',') {
4575 end++;
4576 name = end;
4577 if (*end == '-')
4578 end++;
4579 while (isdigit(*end))
4580 end++;
4581 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4582 }
4583
4584 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4585 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4586 " occurrences values smaller than %d.\n",
4587 file, linenum, MAX_HDR_HISTORY);
4588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
4590 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004591 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004592 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4593 if (!sk) {
4594 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
4597 }
4598 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004599 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004600 }
4601 global.last_checks |= LSTCHK_NETADM;
4602#if !defined(CONFIG_HAP_LINUX_TPROXY)
4603 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004604#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004605#else /* no TPROXY support */
4606 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004607 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004610#endif
4611 cur_arg += 2;
4612 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004613 }
4614
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004615 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4616#ifdef SO_BINDTODEVICE
4617 if (!*args[cur_arg + 1]) {
4618 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004620 err_code |= ERR_ALERT | ERR_FATAL;
4621 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004622 }
4623 if (curproxy->iface_name)
4624 free(curproxy->iface_name);
4625
4626 curproxy->iface_name = strdup(args[cur_arg + 1]);
4627 curproxy->iface_len = strlen(curproxy->iface_name);
4628 global.last_checks |= LSTCHK_NETADM;
4629#else
4630 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4631 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004634#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004635 cur_arg += 2;
4636 continue;
4637 }
4638 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4639 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004643 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004644 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4645 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4646 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004651 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004656 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004657
4658 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4659 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004660 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004661 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004663 }
4664 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004665 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4666 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004667 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004668 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004670 }
4671 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004672 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4673 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004674 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004675 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 }
4678 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004679 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4680 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004681 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004682 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 }
4685 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004686 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4687 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004688 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004689 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004691 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004692 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004693 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4694 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004695 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004696 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004697 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004698 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004699 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004700 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4701 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004702 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004703 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004704 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004705 }
4706 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004707 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4708 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004709 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004710 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004711 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004713 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004714 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004715 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4716 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004717 err_code |= ERR_ALERT | ERR_FATAL;
4718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004719 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004720
4721 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4722 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004723 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004724 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004725 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004726 }
4727 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004728 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4729 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004730 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004731 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 }
4734 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004735 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4736 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004737 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004738 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 }
4741 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004742 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4743 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004744 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004745 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747 }
4748 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004749 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4750 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004751 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004752 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004755 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004756 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4757 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004758 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004759 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004760 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004761 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004762 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004763 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004764
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765 if (curproxy == &defproxy) {
4766 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004767 err_code |= ERR_ALERT | ERR_FATAL;
4768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004770 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004771 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 if (*(args[1]) == 0) {
4774 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004778
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004779 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4780 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4781 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4782 file, linenum, args[0]);
4783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
4785 }
4786 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4787 }
4788 else if (*args[2]) {
4789 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4790 file, linenum, args[0], args[2]);
4791 err_code |= ERR_ALERT | ERR_FATAL;
4792 goto out;
4793 }
4794
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004795 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004796 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004797 wl->s = strdup(args[1]);
4798 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004799 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 }
4801 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004802 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4804 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004805 err_code |= ERR_ALERT | ERR_FATAL;
4806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004807 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004808
Willy Tarreauade5ec42010-01-28 19:33:49 +01004809 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4810 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004811 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004812 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 }
4815 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004816 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4817 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004818 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004819 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004821 }
4822 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004823 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4824 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004825 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004826 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004828 }
4829 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004830 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4832 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 }
4836
Willy Tarreauade5ec42010-01-28 19:33:49 +01004837 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4838 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004839 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004840 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 }
4843 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004844 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4845 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004846 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004847 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 }
4850 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004851 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4852 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004853 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004854 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004856 }
4857 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004858 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004859
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 if (curproxy == &defproxy) {
4861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004865 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004866 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 if (*(args[1]) == 0) {
4869 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 }
4873
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004874 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4875 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4876 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4877 file, linenum, args[0]);
4878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
4880 }
4881 err_code |= warnif_cond_requires_req(cond, file, linenum);
4882 }
4883 else if (*args[2]) {
4884 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4885 file, linenum, args[0], args[2]);
4886 err_code |= ERR_ALERT | ERR_FATAL;
4887 goto out;
4888 }
4889
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004890 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004891 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004892 wl->s = strdup(args[1]);
4893 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
4895 else if (!strcmp(args[0], "errorloc") ||
4896 !strcmp(args[0], "errorloc302") ||
4897 !strcmp(args[0], "errorloc303")) { /* error location */
4898 int errnum, errlen;
4899 char *err;
4900
Willy Tarreau977b8e42006-12-29 14:19:17 +01004901 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004902 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004903
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004905 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004906 err_code |= ERR_ALERT | ERR_FATAL;
4907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 }
4909
4910 errnum = atol(args[1]);
4911 if (!strcmp(args[0], "errorloc303")) {
4912 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4913 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4914 } else {
4915 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4916 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4917 }
4918
Willy Tarreau0f772532006-12-23 20:51:41 +01004919 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4920 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004921 chunk_destroy(&curproxy->errmsg[rc]);
4922 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004923 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004926
4927 if (rc >= HTTP_ERR_SIZE) {
4928 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4929 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 free(err);
4931 }
4932 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004933 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4934 int errnum, errlen, fd;
4935 char *err;
4936 struct stat stat;
4937
4938 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004939 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004940
4941 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004942 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004945 }
4946
4947 fd = open(args[2], O_RDONLY);
4948 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4949 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4950 file, linenum, args[2], args[1]);
4951 if (fd >= 0)
4952 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004955 }
4956
Willy Tarreau27a674e2009-08-17 07:23:33 +02004957 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004958 errlen = stat.st_size;
4959 } else {
4960 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004961 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004962 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004963 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004964 }
4965
4966 err = malloc(errlen); /* malloc() must succeed during parsing */
4967 errnum = read(fd, err, errlen);
4968 if (errnum != errlen) {
4969 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4970 file, linenum, args[2], args[1]);
4971 close(fd);
4972 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004975 }
4976 close(fd);
4977
4978 errnum = atol(args[1]);
4979 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4980 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004981 chunk_destroy(&curproxy->errmsg[rc]);
4982 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004983 break;
4984 }
4985 }
4986
4987 if (rc >= HTTP_ERR_SIZE) {
4988 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4989 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004990 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004991 free(err);
4992 }
4993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004995 struct cfg_kw_list *kwl;
4996 int index;
4997
4998 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4999 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5000 if (kwl->kw[index].section != CFG_LISTEN)
5001 continue;
5002 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5003 /* prepare error message just in case */
5004 snprintf(trash, sizeof(trash),
5005 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005006 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5007 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005008 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005009 err_code |= ERR_ALERT | ERR_FATAL;
5010 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005011 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005012 else if (rc > 0) {
5013 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005014 err_code |= ERR_WARN;
5015 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005016 }
Willy Tarreau93893792009-07-23 13:19:11 +02005017 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005018 }
5019 }
5020 }
5021
Willy Tarreau6daf3432008-01-22 16:44:08 +01005022 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
Willy Tarreau93893792009-07-23 13:19:11 +02005026 out:
5027 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028}
5029
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005030int
5031cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5032{
5033
5034 int err_code = 0;
5035 const char *err;
5036
5037 if (!strcmp(args[0], "userlist")) { /* new userlist */
5038 struct userlist *newul;
5039
5040 if (!*args[1]) {
5041 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5042 file, linenum, args[0]);
5043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
5045 }
5046
5047 err = invalid_char(args[1]);
5048 if (err) {
5049 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5050 file, linenum, *err, args[0], args[1]);
5051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
5053 }
5054
5055 for (newul = userlist; newul; newul = newul->next)
5056 if (!strcmp(newul->name, args[1])) {
5057 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5058 file, linenum, args[1]);
5059 err_code |= ERR_WARN;
5060 goto out;
5061 }
5062
5063 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5064 if (!newul) {
5065 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5066 err_code |= ERR_ALERT | ERR_ABORT;
5067 goto out;
5068 }
5069
5070 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5071 newul->name = strdup(args[1]);
5072
5073 if (!newul->groupusers | !newul->name) {
5074 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5075 err_code |= ERR_ALERT | ERR_ABORT;
5076 goto out;
5077 }
5078
5079 newul->next = userlist;
5080 userlist = newul;
5081
5082 } else if (!strcmp(args[0], "group")) { /* new group */
5083 int cur_arg, i;
5084 const char *err;
5085
5086 if (!*args[1]) {
5087 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5088 file, linenum, args[0]);
5089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
5091 }
5092
5093 err = invalid_char(args[1]);
5094 if (err) {
5095 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5096 file, linenum, *err, args[0], args[1]);
5097 err_code |= ERR_ALERT | ERR_FATAL;
5098 goto out;
5099 }
5100
5101 for(i = 0; i < userlist->grpcnt; i++)
5102 if (!strcmp(userlist->groups[i], args[1])) {
5103 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5104 file, linenum, args[1], userlist->name);
5105 err_code |= ERR_ALERT;
5106 goto out;
5107 }
5108
5109 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5110 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5111 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
5114 }
5115
5116 cur_arg = 2;
5117
5118 while (*args[cur_arg]) {
5119 if (!strcmp(args[cur_arg], "users")) {
5120 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5121 cur_arg += 2;
5122 continue;
5123 } else {
5124 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5125 file, linenum, args[0]);
5126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
5128 }
5129 }
5130
5131 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5132 } else if (!strcmp(args[0], "user")) { /* new user */
5133 struct auth_users *newuser;
5134 int cur_arg;
5135
5136 if (!*args[1]) {
5137 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5138 file, linenum, args[0]);
5139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
5141 }
5142
5143 for (newuser = userlist->users; newuser; newuser = newuser->next)
5144 if (!strcmp(newuser->user, args[1])) {
5145 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5146 file, linenum, args[1], userlist->name);
5147 err_code |= ERR_ALERT;
5148 goto out;
5149 }
5150
5151 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5152 if (!newuser) {
5153 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5154 err_code |= ERR_ALERT | ERR_ABORT;
5155 goto out;
5156 }
5157
5158 newuser->user = strdup(args[1]);
5159
5160 newuser->next = userlist->users;
5161 userlist->users = newuser;
5162
5163 cur_arg = 2;
5164
5165 while (*args[cur_arg]) {
5166 if (!strcmp(args[cur_arg], "password")) {
5167#ifndef CONFIG_HAP_CRYPT
5168 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5169 file, linenum);
5170 err_code |= ERR_ALERT;
5171#endif
5172 newuser->pass = strdup(args[cur_arg + 1]);
5173 cur_arg += 2;
5174 continue;
5175 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5176 newuser->pass = strdup(args[cur_arg + 1]);
5177 newuser->flags |= AU_O_INSECURE;
5178 cur_arg += 2;
5179 continue;
5180 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005181 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005182 cur_arg += 2;
5183 continue;
5184 } else {
5185 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5186 file, linenum, args[0]);
5187 err_code |= ERR_ALERT | ERR_FATAL;
5188 goto out;
5189 }
5190 }
5191 } else {
5192 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5193 err_code |= ERR_ALERT | ERR_FATAL;
5194 }
5195
5196out:
5197 return err_code;
5198}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199
5200/*
5201 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005202 * Returns the error code, 0 if OK, or any combination of :
5203 * - ERR_ABORT: must abort ASAP
5204 * - ERR_FATAL: we can continue parsing but not start the service
5205 * - ERR_WARN: a warning has been emitted
5206 * - ERR_ALERT: an alert has been emitted
5207 * Only the two first ones can stop processing, the two others are just
5208 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005210int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005211{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005212 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 FILE *f;
5214 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005215 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005216 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218 if ((f=fopen(file,"r")) == NULL)
5219 return -1;
5220
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005221 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005222 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005223 char *end;
5224 char *args[MAX_LINE_ARGS + 1];
5225 char *line = thisline;
5226
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 linenum++;
5228
5229 end = line + strlen(line);
5230
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005231 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5232 /* Check if we reached the limit and the last char is not \n.
5233 * Watch out for the last line without the terminating '\n'!
5234 */
5235 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005236 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005237 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005238 }
5239
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005241 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 line++;
5243
5244 arg = 0;
5245 args[arg] = line;
5246
5247 while (*line && arg < MAX_LINE_ARGS) {
5248 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5249 * C equivalent value. Other combinations left unchanged (eg: \1).
5250 */
5251 if (*line == '\\') {
5252 int skip = 0;
5253 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5254 *line = line[1];
5255 skip = 1;
5256 }
5257 else if (line[1] == 'r') {
5258 *line = '\r';
5259 skip = 1;
5260 }
5261 else if (line[1] == 'n') {
5262 *line = '\n';
5263 skip = 1;
5264 }
5265 else if (line[1] == 't') {
5266 *line = '\t';
5267 skip = 1;
5268 }
5269 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005270 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 unsigned char hex1, hex2;
5272 hex1 = toupper(line[2]) - '0';
5273 hex2 = toupper(line[3]) - '0';
5274 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5275 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5276 *line = (hex1<<4) + hex2;
5277 skip = 3;
5278 }
5279 else {
5280 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005281 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 }
5283 }
5284 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005285 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 end -= skip;
5287 }
5288 line++;
5289 }
5290 else if (*line == '#' || *line == '\n' || *line == '\r') {
5291 /* end of string, end of loop */
5292 *line = 0;
5293 break;
5294 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005295 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005297 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005298 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 line++;
5300 args[++arg] = line;
5301 }
5302 else {
5303 line++;
5304 }
5305 }
5306
5307 /* empty line */
5308 if (!**args)
5309 continue;
5310
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005311 if (*line) {
5312 /* we had to stop due to too many args.
5313 * Let's terminate the string, print the offending part then cut the
5314 * last arg.
5315 */
5316 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5317 line++;
5318 *line = '\0';
5319
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005320 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005321 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005322 err_code |= ERR_ALERT | ERR_FATAL;
5323 args[arg] = line;
5324 }
5325
Willy Tarreau540abe42007-05-02 20:50:16 +02005326 /* zero out remaining args and ensure that at least one entry
5327 * is zeroed out.
5328 */
5329 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 args[arg] = line;
5331 }
5332
Willy Tarreau3842f002009-06-14 11:39:52 +02005333 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005334 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005335 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005336 for (arg=0; *args[arg+1]; arg++)
5337 args[arg] = args[arg+1]; // shift args after inversion
5338 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005339 else if (!strcmp(args[0], "default")) {
5340 kwm = KWM_DEF;
5341 for (arg=0; *args[arg+1]; arg++)
5342 args[arg] = args[arg+1]; // shift args after inversion
5343 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005344
Willy Tarreau3842f002009-06-14 11:39:52 +02005345 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5346 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005347 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005348 }
5349
Willy Tarreau977b8e42006-12-29 14:19:17 +01005350 if (!strcmp(args[0], "listen") ||
5351 !strcmp(args[0], "frontend") ||
5352 !strcmp(args[0], "backend") ||
5353 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005354 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005355 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005356 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005357 cursection = strdup(args[0]);
5358 }
5359 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005361 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005362 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005363 }
5364 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005365 confsect = CFG_USERLIST;
5366 free(cursection);
5367 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005368 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005369 else if (!strcmp(args[0], "peers")) {
5370 confsect = CFG_PEERS;
5371 free(cursection);
5372 cursection = strdup(args[0]);
5373 }
5374
Willy Tarreaubaaee002006-06-26 02:48:02 +02005375 /* else it's a section keyword */
5376
5377 switch (confsect) {
5378 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005379 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005380 break;
5381 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005382 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005384 case CFG_USERLIST:
5385 err_code |= cfg_parse_users(file, linenum, args, kwm);
5386 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005387 case CFG_PEERS:
5388 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5389 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005391 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005392 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005394
5395 if (err_code & ERR_ABORT)
5396 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005398 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005399 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005401 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005402}
5403
Willy Tarreaubb925012009-07-23 13:36:36 +02005404/*
5405 * Returns the error code, 0 if OK, or any combination of :
5406 * - ERR_ABORT: must abort ASAP
5407 * - ERR_FATAL: we can continue parsing but not start the service
5408 * - ERR_WARN: a warning has been emitted
5409 * - ERR_ALERT: an alert has been emitted
5410 * Only the two first ones can stop processing, the two others are just
5411 * indicators.
5412 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005413int check_config_validity()
5414{
5415 int cfgerr = 0;
5416 struct proxy *curproxy = NULL;
5417 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005418 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005419 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005420 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421
5422 /*
5423 * Now, check for the integrity of all that we have collected.
5424 */
5425
5426 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005427 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005428
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005429 /* first, we will invert the proxy list order */
5430 curproxy = NULL;
5431 while (proxy) {
5432 struct proxy *next;
5433
5434 next = proxy->next;
5435 proxy->next = curproxy;
5436 curproxy = proxy;
5437 if (!next)
5438 break;
5439 proxy = next;
5440 }
5441
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005443 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446 }
5447
5448 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005449 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005450 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005451 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005452 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005453 unsigned int next_id;
5454
5455 if (!curproxy->uuid) {
5456 /* proxy ID not set, use automatic numbering with first
5457 * spare entry starting with next_pxid.
5458 */
5459 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5460 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5461 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005462 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005463 next_pxid++;
5464
Willy Tarreau55ea7572007-06-17 19:56:27 +02005465
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005467 /* ensure we don't keep listeners uselessly bound */
5468 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 curproxy = curproxy->next;
5470 continue;
5471 }
5472
Willy Tarreauff01a212009-03-15 13:46:16 +01005473 switch (curproxy->mode) {
5474 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005475 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005476 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005477 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5478 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005479 cfgerr++;
5480 }
5481
5482 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005483 Warning("config : servers will be ignored for %s '%s'.\n",
5484 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005485 break;
5486
5487 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005488 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005489 break;
5490
5491 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005492 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005493 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005494 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5495 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005496 cfgerr++;
5497 }
5498 break;
5499 }
5500
5501 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005502 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5503 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005504 cfgerr++;
5505 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005506
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005507 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005508 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005509 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005510 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5511 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005512 cfgerr++;
5513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005515 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005516 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5517 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005518 cfgerr++;
5519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005521 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005522 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5523 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005524 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005525 }
5526 }
5527 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
5528 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
5529 /* If no LB algo is set in a backend, and we're not in
5530 * transparent mode, dispatch mode nor proxy mode, we
5531 * want to use balance roundrobin by default.
5532 */
5533 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5534 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 }
5536 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005537
Willy Tarreau82936582007-11-30 15:20:09 +01005538 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5539 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005540 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5541 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005542 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005543 }
5544
Willy Tarreauef781042010-01-27 11:53:01 +01005545 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5546 curproxy->options &= ~PR_O2_CHK_SNDST;
5547 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5548 "send-state", proxy_type_str(curproxy), curproxy->id);
5549 err_code |= ERR_WARN;
5550 }
5551
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005552 /* if a default backend was specified, let's find it */
5553 if (curproxy->defbe.name) {
5554 struct proxy *target;
5555
Alex Williams96532db2009-11-01 21:27:13 -05005556 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005557 if (!target) {
5558 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5559 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005560 cfgerr++;
5561 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005562 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5563 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005564 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005565 } else {
5566 free(curproxy->defbe.name);
5567 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005568 /* we force the backend to be present on at least all of
5569 * the frontend's processes.
5570 */
5571 target->bind_proc = curproxy->bind_proc ?
5572 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005573 }
5574 }
5575
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005576 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005577 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5578 /* map jump target for ACT_SETBE in req_rep chain */
5579 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005580 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005581 struct proxy *target;
5582
Willy Tarreaua496b602006-12-17 23:15:24 +01005583 if (exp->action != ACT_SETBE)
5584 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005585
Alex Williams96532db2009-11-01 21:27:13 -05005586 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005587 if (!target) {
5588 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5589 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005590 cfgerr++;
5591 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005592 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5593 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005594 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005595 } else {
5596 free((void *)exp->replace);
5597 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005598 /* we force the backend to be present on at least all of
5599 * the frontend's processes.
5600 */
5601 target->bind_proc = curproxy->bind_proc ?
5602 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005603 }
5604 }
5605 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005606
5607 /* find the target proxy for 'use_backend' rules */
5608 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005609 struct proxy *target;
5610
Alex Williams96532db2009-11-01 21:27:13 -05005611 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005612
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005613 if (!target) {
5614 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5615 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005616 cfgerr++;
5617 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005618 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5619 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005620 cfgerr++;
5621 } else {
5622 free((void *)rule->be.name);
5623 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005624 /* we force the backend to be present on at least all of
5625 * the frontend's processes.
5626 */
5627 target->bind_proc = curproxy->bind_proc ?
5628 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005629 }
5630 }
5631
Emeric Brunb982a3d2010-01-04 15:45:53 +01005632 /* find the target table for 'stick' rules */
5633 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5634 struct proxy *target;
5635
Emeric Brun1d33b292010-01-04 15:47:17 +01005636 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5637 if (mrule->flags & STK_IS_STORE)
5638 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5639
Emeric Brunb982a3d2010-01-04 15:45:53 +01005640 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005641 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005642 else
5643 target = curproxy;
5644
5645 if (!target) {
5646 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5647 curproxy->id, mrule->table.name);
5648 cfgerr++;
5649 }
5650 else if (target->table.size == 0) {
5651 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5652 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5653 cfgerr++;
5654 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005655 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005656 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5657 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5658 cfgerr++;
5659 }
5660 else {
5661 free((void *)mrule->table.name);
5662 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005663 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005664 }
5665 }
5666
5667 /* find the target table for 'store response' rules */
5668 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5669 struct proxy *target;
5670
Emeric Brun1d33b292010-01-04 15:47:17 +01005671 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5672
Emeric Brunb982a3d2010-01-04 15:45:53 +01005673 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005674 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005675 else
5676 target = curproxy;
5677
5678 if (!target) {
5679 Alert("Proxy '%s': unable to find store table '%s'.\n",
5680 curproxy->id, mrule->table.name);
5681 cfgerr++;
5682 }
5683 else if (target->table.size == 0) {
5684 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5685 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5686 cfgerr++;
5687 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005688 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005689 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5690 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5691 cfgerr++;
5692 }
5693 else {
5694 free((void *)mrule->table.name);
5695 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005696 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005697 }
5698 }
5699
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005700 /* find the target table for 'tcp-request' layer 4 rules */
5701 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5702 struct proxy *target;
5703
Willy Tarreau56123282010-08-06 19:06:56 +02005704 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005705 continue;
5706
5707 if (trule->act_prm.trk_ctr.table.n)
5708 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5709 else
5710 target = curproxy;
5711
5712 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005713 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5714 curproxy->id, trule->act_prm.trk_ctr.table.n,
5715 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005716 cfgerr++;
5717 }
5718 else if (target->table.size == 0) {
5719 Alert("Proxy '%s': table '%s' used but not configured.\n",
5720 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5721 cfgerr++;
5722 }
5723 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005724 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 +02005725 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5726 cfgerr++;
5727 }
5728 else {
5729 free(trule->act_prm.trk_ctr.table.n);
5730 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005731 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005732 * to pass a list of counters to track and allocate them right here using
5733 * stktable_alloc_data_type().
5734 */
5735 }
5736 }
5737
Willy Tarreaud1f96522010-08-03 19:34:32 +02005738 /* find the target table for 'tcp-request' layer 6 rules */
5739 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5740 struct proxy *target;
5741
Willy Tarreau56123282010-08-06 19:06:56 +02005742 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005743 continue;
5744
5745 if (trule->act_prm.trk_ctr.table.n)
5746 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5747 else
5748 target = curproxy;
5749
5750 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005751 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5752 curproxy->id, trule->act_prm.trk_ctr.table.n,
5753 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005754 cfgerr++;
5755 }
5756 else if (target->table.size == 0) {
5757 Alert("Proxy '%s': table '%s' used but not configured.\n",
5758 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5759 cfgerr++;
5760 }
5761 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005762 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 +02005763 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5764 cfgerr++;
5765 }
5766 else {
5767 free(trule->act_prm.trk_ctr.table.n);
5768 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005769 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005770 * to pass a list of counters to track and allocate them right here using
5771 * stktable_alloc_data_type().
5772 */
5773 }
5774 }
5775
Emeric Brun32da3c42010-09-23 18:39:19 +02005776 if (curproxy->table.peers.name) {
5777 struct peers *curpeers = peers;
5778
5779 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5780 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5781 free((void *)curproxy->table.peers.name);
5782 curproxy->table.peers.p = peers;
5783 break;
5784 }
5785 }
5786
5787 if (!curpeers) {
5788 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5789 curproxy->id, curproxy->table.peers.name);
5790 cfgerr++;
5791 }
5792 else if (!curpeers->peers_fe) {
5793 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5794 curproxy->id, curpeers->id);
5795 cfgerr++;
5796 }
5797 }
5798
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005799 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5800 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005801 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5802 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5803 "proxy", curproxy->id);
5804 cfgerr++;
5805 goto out_uri_auth_compat;
5806 }
5807
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005808 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005809 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005810 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005811 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005812
Willy Tarreau95fa4692010-02-01 13:05:50 +01005813 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5814 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005815
5816 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005817 uri_auth_compat_req[i++] = "realm";
5818 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5819 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005820
Willy Tarreau95fa4692010-02-01 13:05:50 +01005821 uri_auth_compat_req[i++] = "unless";
5822 uri_auth_compat_req[i++] = "{";
5823 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5824 uri_auth_compat_req[i++] = "}";
5825 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005826
Willy Tarreau95fa4692010-02-01 13:05:50 +01005827 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5828 if (!req_acl) {
5829 cfgerr++;
5830 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005831 }
5832
Willy Tarreau95fa4692010-02-01 13:05:50 +01005833 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5834
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005835 if (curproxy->uri_auth->auth_realm) {
5836 free(curproxy->uri_auth->auth_realm);
5837 curproxy->uri_auth->auth_realm = NULL;
5838 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005839
5840 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005841 }
5842out_uri_auth_compat:
5843
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005844 cfgerr += acl_find_targets(curproxy);
5845
Willy Tarreau2738a142006-07-08 17:28:09 +02005846 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005847 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005848 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005849 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005850 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005851 " | While not properly invalid, you will certainly encounter various problems\n"
5852 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005853 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005854 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005855 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005856 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005857
Willy Tarreau1fa31262007-12-03 00:36:16 +01005858 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5859 * We must still support older configurations, so let's find out whether those
5860 * parameters have been set or must be copied from contimeouts.
5861 */
5862 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005863 if (!curproxy->timeout.tarpit ||
5864 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005865 /* tarpit timeout not set. We search in the following order:
5866 * default.tarpit, curr.connect, default.connect.
5867 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005868 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005869 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005870 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005871 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005872 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005873 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005874 }
5875 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005876 (!curproxy->timeout.queue ||
5877 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005878 /* queue timeout not set. We search in the following order:
5879 * default.queue, curr.connect, default.connect.
5880 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005881 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005882 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005883 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005884 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005885 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005886 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005887 }
5888 }
5889
Willy Tarreau07a54902010-03-29 18:33:29 +02005890 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005891 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5892 curproxy->check_req = (char *)malloc(curproxy->check_len);
5893 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005894 }
5895
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005896 /* The small pools required for the capture lists */
5897 if (curproxy->nb_req_cap)
5898 curproxy->req_cap_pool = create_pool("ptrcap",
5899 curproxy->nb_req_cap * sizeof(char *),
5900 MEM_F_SHARED);
5901 if (curproxy->nb_rsp_cap)
5902 curproxy->rsp_cap_pool = create_pool("ptrcap",
5903 curproxy->nb_rsp_cap * sizeof(char *),
5904 MEM_F_SHARED);
5905
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005906 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5907 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5908 MEM_F_SHARED);
5909
Willy Tarreau86034312006-12-29 00:10:33 +01005910 /* for backwards compatibility with "listen" instances, if
5911 * fullconn is not set but maxconn is set, then maxconn
5912 * is used.
5913 */
5914 if (!curproxy->fullconn)
5915 curproxy->fullconn = curproxy->maxconn;
5916
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 /* first, we will invert the servers list order */
5918 newsrv = NULL;
5919 while (curproxy->srv) {
5920 struct server *next;
5921
5922 next = curproxy->srv->next;
5923 curproxy->srv->next = newsrv;
5924 newsrv = curproxy->srv;
5925 if (!next)
5926 break;
5927 curproxy->srv = next;
5928 }
5929
Willy Tarreaudd701652010-05-25 23:03:02 +02005930 /* assign automatic UIDs to servers which don't have one yet */
5931 next_id = 1;
5932 newsrv = curproxy->srv;
5933 while (newsrv != NULL) {
5934 if (!newsrv->puid) {
5935 /* server ID not set, use automatic numbering with first
5936 * spare entry starting with next_svid.
5937 */
5938 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5939 newsrv->conf.id.key = newsrv->puid = next_id;
5940 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5941 }
5942 next_id++;
5943 newsrv = newsrv->next;
5944 }
5945
Willy Tarreau20697042007-11-15 23:26:18 +01005946 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005947 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005948
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005949 /* We have to initialize the server lookup mechanism depending
5950 * on what LB algorithm was choosen.
5951 */
5952
5953 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5954 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5955 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005956 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5957 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5958 init_server_map(curproxy);
5959 } else {
5960 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5961 fwrr_init_server_groups(curproxy);
5962 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005963 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005964
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005965 case BE_LB_KIND_LC:
5966 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005967 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005968 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005969
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005970 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005971 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5972 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5973 chash_init_server_tree(curproxy);
5974 } else {
5975 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5976 init_server_map(curproxy);
5977 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005978 break;
5979 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980
5981 if (curproxy->options & PR_O_LOGASAP)
5982 curproxy->to_log &= ~LW_BYTES;
5983
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005984 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5985 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5986 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5987 proxy_type_str(curproxy), curproxy->id);
5988 err_code |= ERR_WARN;
5989 }
5990
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005991 if (curproxy->mode != PR_MODE_HTTP) {
5992 int optnum;
5993
5994 if (curproxy->options & PR_O_COOK_ANY) {
5995 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5996 proxy_type_str(curproxy), curproxy->id);
5997 err_code |= ERR_WARN;
5998 }
5999
6000 if (curproxy->uri_auth) {
6001 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6002 proxy_type_str(curproxy), curproxy->id);
6003 err_code |= ERR_WARN;
6004 curproxy->uri_auth = NULL;
6005 }
6006
6007 if (curproxy->options & PR_O_FWDFOR) {
6008 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6009 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6010 err_code |= ERR_WARN;
6011 curproxy->options &= ~PR_O_FWDFOR;
6012 }
6013
6014 if (curproxy->options & PR_O_ORGTO) {
6015 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6016 "originalto", proxy_type_str(curproxy), curproxy->id);
6017 err_code |= ERR_WARN;
6018 curproxy->options &= ~PR_O_ORGTO;
6019 }
6020
6021 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6022 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6023 (curproxy->cap & cfg_opts[optnum].cap) &&
6024 (curproxy->options & cfg_opts[optnum].val)) {
6025 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6026 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6027 err_code |= ERR_WARN;
6028 curproxy->options &= ~cfg_opts[optnum].val;
6029 }
6030 }
6031
6032 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6033 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6034 (curproxy->cap & cfg_opts2[optnum].cap) &&
6035 (curproxy->options2 & cfg_opts2[optnum].val)) {
6036 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6037 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6038 err_code |= ERR_WARN;
6039 curproxy->options2 &= ~cfg_opts2[optnum].val;
6040 }
6041 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006042
Willy Tarreauefa5f512010-03-30 20:13:29 +02006043#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006044 if (curproxy->bind_hdr_occ) {
6045 curproxy->bind_hdr_occ = 0;
6046 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6047 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6048 err_code |= ERR_WARN;
6049 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006050#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006051 }
6052
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006054 * ensure that we're not cross-dressing a TCP server into HTTP.
6055 */
6056 newsrv = curproxy->srv;
6057 while (newsrv != NULL) {
6058 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006059 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6060 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006061 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006062 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006063
Willy Tarreauefa5f512010-03-30 20:13:29 +02006064#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006065 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6066 newsrv->bind_hdr_occ = 0;
6067 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6068 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6069 err_code |= ERR_WARN;
6070 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006071#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006072 newsrv = newsrv->next;
6073 }
6074
6075 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006076 * If this server supports a maxconn parameter, it needs a dedicated
6077 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006078 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006079 */
6080 newsrv = curproxy->srv;
6081 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006082 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006083 /* Only 'minconn' was specified, or it was higher than or equal
6084 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6085 * this will avoid further useless expensive computations.
6086 */
6087 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006088 } else if (newsrv->maxconn && !newsrv->minconn) {
6089 /* minconn was not specified, so we set it to maxconn */
6090 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006091 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006092 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6093 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006094 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006095 }
6096
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006097 if (newsrv->trackit) {
6098 struct proxy *px;
6099 struct server *srv;
6100 char *pname, *sname;
6101
6102 pname = newsrv->trackit;
6103 sname = strrchr(pname, '/');
6104
6105 if (sname)
6106 *sname++ = '\0';
6107 else {
6108 sname = pname;
6109 pname = NULL;
6110 }
6111
6112 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006113 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006114 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006115 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6116 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006117 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006118 cfgerr++;
6119 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006120 }
6121 } else
6122 px = curproxy;
6123
6124 srv = findserver(px, sname);
6125 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006126 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6127 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006128 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006129 cfgerr++;
6130 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006131 }
6132
6133 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006134 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006135 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006136 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006137 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006138 cfgerr++;
6139 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006140 }
6141
6142 if (curproxy != px &&
6143 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006144 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006145 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006146 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006147 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006148 cfgerr++;
6149 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006150 }
6151
6152 newsrv->tracked = srv;
6153 newsrv->tracknext = srv->tracknext;
6154 srv->tracknext = newsrv;
6155
6156 free(newsrv->trackit);
6157 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006158 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 newsrv = newsrv->next;
6160 }
6161
Willy Tarreauc1a21672009-08-16 22:37:44 +02006162 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006163 curproxy->accept = frontend_accept;
6164
Willy Tarreauc1a21672009-08-16 22:37:44 +02006165 if (curproxy->tcp_req.inspect_delay ||
6166 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006167 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006168
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006169 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006170 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006171 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006172 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006173
6174 /* both TCP and HTTP must check switching rules */
6175 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6176 }
6177
6178 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006179 if (curproxy->tcp_req.inspect_delay ||
6180 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6181 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6182
Emeric Brun97679e72010-09-23 17:56:44 +02006183 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6184 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6185
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006186 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006187 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006188 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006189 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006190
6191 /* If the backend does requires RDP cookie persistence, we have to
6192 * enable the corresponding analyser.
6193 */
6194 if (curproxy->options2 & PR_O2_RDPC_PRST)
6195 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6196 }
6197
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006198 listener = NULL;
6199 while (curproxy->listen) {
6200 struct listener *next;
6201
6202 next = curproxy->listen->next;
6203 curproxy->listen->next = listener;
6204 listener = curproxy->listen;
6205
6206 if (!next)
6207 break;
6208
6209 curproxy->listen = next;
6210 }
6211
Willy Tarreaue6b98942007-10-29 01:09:36 +01006212 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006213 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006214 listener = curproxy->listen;
6215 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006216 if (!listener->luid) {
6217 /* listener ID not set, use automatic numbering with first
6218 * spare entry starting with next_luid.
6219 */
6220 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6221 listener->conf.id.key = listener->luid = next_id;
6222 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006223 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006224 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006225
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006226 /* enable separate counters */
6227 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6228 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6229 if (!listener->name) {
6230 sprintf(trash, "sock-%d", listener->luid);
6231 listener->name = strdup(trash);
6232 }
6233 }
6234
Willy Tarreaue6b98942007-10-29 01:09:36 +01006235 if (curproxy->options & PR_O_TCP_NOLING)
6236 listener->options |= LI_O_NOLINGER;
6237 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006238 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006239 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006240 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006241 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006242 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006243 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006244
Willy Tarreau8a956912010-10-15 14:27:08 +02006245 if (listener->options & LI_O_ACC_PROXY)
6246 listener->analysers |= AN_REQ_DECODE_PROXY;
6247
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006248 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6249 listener->options |= LI_O_TCP_RULES;
6250
Willy Tarreaude3041d2010-05-31 10:56:17 +02006251 if (curproxy->mon_mask.s_addr)
6252 listener->options |= LI_O_CHK_MONNET;
6253
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006254 /* smart accept mode is automatic in HTTP mode */
6255 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6256 (curproxy->mode == PR_MODE_HTTP &&
6257 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6258 listener->options |= LI_O_NOQUICKACK;
6259
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006260 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006261 listener = listener->next;
6262 }
6263
Willy Tarreaubaaee002006-06-26 02:48:02 +02006264 curproxy = curproxy->next;
6265 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006266
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006267 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6268 struct auth_users *curuser;
6269 int g;
6270
6271 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6272 unsigned int group_mask = 0;
6273 char *group = NULL;
6274
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006275 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006276 continue;
6277
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006278 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006279
6280 for (g = 0; g < curuserlist->grpcnt; g++)
6281 if (!strcmp(curuserlist->groups[g], group))
6282 break;
6283
6284 if (g == curuserlist->grpcnt) {
6285 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6286 curuserlist->name, group, curuser->user);
6287 err_code |= ERR_ALERT | ERR_FATAL;
6288 goto out;
6289 }
6290
6291 group_mask |= (1 << g);
6292 }
6293
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006294 free(curuser->u.groups);
6295 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006296 }
6297
6298 for (g = 0; g < curuserlist->grpcnt; g++) {
6299 char *user = NULL;
6300
6301 if (!curuserlist->groupusers[g])
6302 continue;
6303
6304 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6305 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6306 if (!strcmp(curuser->user, user))
6307 break;
6308
6309 if (!curuser) {
6310 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6311 curuserlist->name, user, curuserlist->groups[g]);
6312 err_code |= ERR_ALERT | ERR_FATAL;
6313 goto out;
6314 }
6315
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006316 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006317 }
6318
6319 free(curuserlist->groupusers[g]);
6320 }
6321
6322 free(curuserlist->groupusers);
6323
6324#ifdef DEBUG_AUTH
6325 for (g = 0; g < curuserlist->grpcnt; g++) {
6326 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6327
6328 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6329 if (curuser->group_mask & (1 << g))
6330 fprintf(stderr, " %s", curuser->user);
6331 }
6332
6333 fprintf(stderr, "\n");
6334 }
6335#endif
6336
6337 }
6338
Willy Tarreau056f5682010-06-06 15:51:11 +02006339 /* initialize stick-tables on backend capable proxies. This must not
6340 * be done earlier because the data size may be discovered while parsing
6341 * other proxies.
6342 */
6343 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006344 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006345
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006346 /*
6347 * Recount currently required checks.
6348 */
6349
6350 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6351 int optnum;
6352
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006353 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6354 if (curproxy->options & cfg_opts[optnum].val)
6355 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006356
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006357 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6358 if (curproxy->options2 & cfg_opts2[optnum].val)
6359 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006360 }
6361
Willy Tarreaubb925012009-07-23 13:36:36 +02006362 if (cfgerr > 0)
6363 err_code |= ERR_ALERT | ERR_FATAL;
6364 out:
6365 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006366}
6367
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006368/*
6369 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6370 * parsing sessions.
6371 */
6372void cfg_register_keywords(struct cfg_kw_list *kwl)
6373{
6374 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6375}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006377/*
6378 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6379 */
6380void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6381{
6382 LIST_DEL(&kwl->list);
6383 LIST_INIT(&kwl->list);
6384}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006385
6386/*
6387 * Local variables:
6388 * c-indent-level: 8
6389 * c-basic-offset: 8
6390 * End:
6391 */