blob: 3841c99f0045aa1ccd4d55f5768c24c1f5e2cc9b [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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020045#include <proto/frontend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010046#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020056#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010057#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010058#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010060#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010062#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063
64
Willy Tarreauf3c69202006-07-09 16:42:34 +020065/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
66 * ssl-hello-chk option to ensure that the remote server speaks SSL.
67 *
68 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
69 */
70const char sslv3_client_hello_pkt[] = {
71 "\x16" /* ContentType : 0x16 = Hanshake */
72 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
73 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
74 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
75 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
76 "\x03\x00" /* Hello Version : 0x0300 = v3 */
77 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
78 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
79 "\x00" /* Session ID length : empty (no session ID) */
80 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
81 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
82 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
83 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
84 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
85 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
86 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
87 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
88 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
89 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
90 "\x00\x38" "\x00\x39" "\x00\x3A"
91 "\x01" /* Compression Length : 0x01 = 1 byte for types */
92 "\x00" /* Compression Type : 0x00 = NULL compression */
93};
94
Willy Tarreau3842f002009-06-14 11:39:52 +020095/* various keyword modifiers */
96enum kw_mod {
97 KWM_STD = 0, /* normal */
98 KWM_NO, /* "no" prefixed before the keyword */
99 KWM_DEF, /* "default" prefixed before the keyword */
100};
101
Willy Tarreau13943ab2006-12-31 00:24:10 +0100102/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100103struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104 const char *name;
105 unsigned int val;
106 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100107 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100108 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100109};
110
111/* proxy->options */
112static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100114 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
115 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
116 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
117 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
118 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
119 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
120 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
121 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
124 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
126 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
127 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
128 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
129 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100130#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100131 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100132#else
133 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100134#endif
135
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100136 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137};
138
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100139/* proxy->options2 */
140static const struct cfg_opt cfg_opts2[] =
141{
142#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
144 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
145 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100146#else
147 { "splice-request", 0, 0, 0, 0 },
148 { "splice-response", 0, 0, 0, 0 },
149 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
152 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
153 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
154 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
155 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
156 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
157 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
158 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
159 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
160 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200161 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162 { NULL, 0, 0, 0 }
163};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164
Willy Tarreau6daf3432008-01-22 16:44:08 +0100165static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
167int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100168int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200170/* List head of all known configuration keywords */
171static struct cfg_kw_list cfg_keywords = {
172 .list = LIST_HEAD_INIT(cfg_keywords.list)
173};
174
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175/*
176 * converts <str> to a list of listeners which are dynamically allocated.
177 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
178 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
179 * - <port> is a numerical port from 1 to 65535 ;
180 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
181 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200182 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185{
186 struct listener *l;
187 char *c, *next, *range, *dupstr;
188 int port, end;
189
190 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200191
Willy Tarreaubaaee002006-06-26 02:48:02 +0200192 while (next && *next) {
193 struct sockaddr_storage ss;
194
195 str = next;
196 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100197 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198 *next++ = 0;
199 }
200
Emeric Bruned760922010-10-22 17:59:25 +0200201 if (*str == '/') {
202 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
203 /* so compute max path */
204 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
205 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 +0200206
Emeric Bruned760922010-10-22 17:59:25 +0200207 if (strlen(str) > max_path_len) {
208 Alert("Socket path '%s' too long (max %d)\n", str, max_path_len);
209 goto fail;
210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200213 ss.ss_family = AF_UNIX;
214 if (global.unix_bind.prefix) {
215 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
216 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217 }
Emeric Bruned760922010-10-22 17:59:25 +0200218 else {
219 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
220 }
221 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 }
223 else {
Emeric Bruned760922010-10-22 17:59:25 +0200224 /* 2) look for the addr/port delimiter, it's the last colon. */
225 if ((range = strrchr(str, ':')) == NULL) {
226 Alert("Missing port number: '%s'\n", str);
227 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 }
Emeric Bruned760922010-10-22 17:59:25 +0200229
230 *range++ = 0;
231
232 if (strrchr(str, ':') != NULL) {
233 /* IPv6 address contains ':' */
234 memset(&ss, 0, sizeof(ss));
235 ss.ss_family = AF_INET6;
236
237 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
238 Alert("Invalid server address: '%s'\n", str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239 goto fail;
240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 }
Emeric Bruned760922010-10-22 17:59:25 +0200242 else {
243 memset(&ss, 0, sizeof(ss));
244 ss.ss_family = AF_INET;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Emeric Bruned760922010-10-22 17:59:25 +0200246 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
247 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
248 }
249 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
250 struct hostent *he;
251
252 if ((he = gethostbyname(str)) == NULL) {
253 Alert("Invalid server name: '%s'\n", str);
254 goto fail;
255 }
256 else
257 ((struct sockaddr_in *)&ss)->sin_addr =
258 *(struct in_addr *) *(he->h_addr_list);
259 }
260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261
Emeric Bruned760922010-10-22 17:59:25 +0200262 /* 3) look for the port-end delimiter */
263 if ((c = strchr(range, '-')) != NULL) {
264 *c++ = 0;
265 end = atol(c);
266 }
267 else {
268 end = atol(range);
269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Emeric Bruned760922010-10-22 17:59:25 +0200271 port = atol(range);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272
Emeric Bruned760922010-10-22 17:59:25 +0200273 if (port < 1 || port > 65535) {
274 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
275 goto fail;
276 }
277
278 if (end < 1 || end > 65535) {
279 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
280 goto fail;
281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282 }
283
284 for (; port <= end; port++) {
285 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200286 l->next = curproxy->listen;
287 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288
289 l->fd = -1;
290 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100291 l->state = LI_INIT;
292
Emeric Bruned760922010-10-22 17:59:25 +0200293 if(ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100295 tcpv4_add_listener(l);
296 }
Emeric Bruned760922010-10-22 17:59:25 +0200297 else if (ss.ss_family == AF_INET6) {
298 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
299 tcpv6_add_listener(l);
300 }
301 else {
302 l->perm.ux.gid = l->perm.ux.uid = -1;
303 l->perm.ux.mode = 0;
304 uxst_add_listener(l);
305 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200306
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200307 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100308 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309 } /* end for(port) */
310 } /* end while(next) */
311 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200312 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200313 fail:
314 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200315 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316}
317
Willy Tarreau977b8e42006-12-29 14:19:17 +0100318/*
319 * Sends a warning if proxy <proxy> does not have at least one of the
320 * capabilities in <cap>. An optionnal <hint> may be added at the end
321 * of the warning to help the user. Returns 1 if a warning was emitted
322 * or 0 if the condition is valid.
323 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100324int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100325{
326 char *msg;
327
328 switch (cap) {
329 case PR_CAP_BE: msg = "no backend"; break;
330 case PR_CAP_FE: msg = "no frontend"; break;
331 case PR_CAP_RS: msg = "no ruleset"; break;
332 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
333 default: msg = "not enough"; break;
334 }
335
336 if (!(proxy->cap & cap)) {
337 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100338 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100339 return 1;
340 }
341 return 0;
342}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200343
Willy Tarreau61d18892009-03-31 10:49:21 +0200344/* Report a warning if a rule is placed after a 'block' rule.
345 * Return 1 if the warning has been emitted, otherwise 0.
346 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100347int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200348{
349 if (!LIST_ISEMPTY(&proxy->block_cond)) {
350 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
351 file, line, arg);
352 return 1;
353 }
354 return 0;
355}
356
357/* Report a warning if a rule is placed after a reqrewrite rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100360int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200361{
362 if (proxy->req_exp) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
370/* Report a warning if a rule is placed after a reqadd rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100375 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
383/* Report a warning if a rule is placed after a redirect rule.
384 * Return 1 if the warning has been emitted, otherwise 0.
385 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
389 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
390 file, line, arg);
391 return 1;
392 }
393 return 0;
394}
395
396/* Report a warning if a rule is placed after a 'use_backend' rule.
397 * Return 1 if the warning has been emitted, otherwise 0.
398 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100399int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200400{
401 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
402 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
403 file, line, arg);
404 return 1;
405 }
406 return 0;
407}
408
409/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100410int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200411{
412 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
413 warnif_rule_after_reqadd(proxy, file, line, arg) ||
414 warnif_rule_after_redirect(proxy, file, line, arg) ||
415 warnif_rule_after_use_backend(proxy, file, line, arg);
416}
417
418/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100419int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200420{
421 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
422 warnif_rule_after_redirect(proxy, file, line, arg) ||
423 warnif_rule_after_use_backend(proxy, file, line, arg);
424}
425
426/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100427int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200428{
429 return warnif_rule_after_redirect(proxy, file, line, arg) ||
430 warnif_rule_after_use_backend(proxy, file, line, arg);
431}
432
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100433/* Report it if a request ACL condition uses some response-only parameters. It
434 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
435 * Note that <cond> may be NULL and then will be ignored.
436 */
437static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
438{
439 struct acl *acl;
440
441 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
442 return 0;
443
444 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
445 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
446 file, line, acl ? acl->name : "(unknown)");
447 return ERR_WARN;
448}
449
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100450/* Report it if a request ACL condition uses some request-only volatile parameters.
451 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
452 * Note that <cond> may be NULL and then will be ignored.
453 */
454static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
455{
456 struct acl *acl;
457
458 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
459 return 0;
460
461 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
462 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
463 file, line, acl ? acl->name : "(unknown)");
464 return ERR_WARN;
465}
466
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100467
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 * parse a line in a <global> section. Returns the error code, 0 if OK, or
470 * any combination of :
471 * - ERR_ABORT: must abort ASAP
472 * - ERR_FATAL: we can continue parsing but not start the service
473 * - ERR_WARN: a warning has been emitted
474 * - ERR_ALERT: an alert has been emitted
475 * Only the two first ones can stop processing, the two others are just
476 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200478int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479{
Willy Tarreau058e9072009-07-20 09:30:05 +0200480 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481
482 if (!strcmp(args[0], "global")) { /* new section */
483 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485 }
486 else if (!strcmp(args[0], "daemon")) {
487 global.mode |= MODE_DAEMON;
488 }
489 else if (!strcmp(args[0], "debug")) {
490 global.mode |= MODE_DEBUG;
491 }
492 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100493 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200495 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100496 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200497 }
498 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100499 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200501 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100502 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100504 else if (!strcmp(args[0], "nosplice")) {
505 global.tune.options &= ~GTUNE_USE_SPLICE;
506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200507 else if (!strcmp(args[0], "quiet")) {
508 global.mode |= MODE_QUIET;
509 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200510 else if (!strcmp(args[0], "tune.maxpollevents")) {
511 if (global.tune.maxpollevents != 0) {
512 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200513 err_code |= ERR_ALERT;
514 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200515 }
516 if (*(args[1]) == 0) {
517 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200518 err_code |= ERR_ALERT | ERR_FATAL;
519 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200520 }
521 global.tune.maxpollevents = atol(args[1]);
522 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100523 else if (!strcmp(args[0], "tune.maxaccept")) {
524 if (global.tune.maxaccept != 0) {
525 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200526 err_code |= ERR_ALERT;
527 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100528 }
529 if (*(args[1]) == 0) {
530 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100533 }
534 global.tune.maxaccept = atol(args[1]);
535 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200536 else if (!strcmp(args[0], "tune.chksize")) {
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
541 }
542 global.tune.chksize = atol(args[1]);
543 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200544 else if (!strcmp(args[0], "tune.bufsize")) {
545 if (*(args[1]) == 0) {
546 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
547 err_code |= ERR_ALERT | ERR_FATAL;
548 goto out;
549 }
550 global.tune.bufsize = atol(args[1]);
551 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
552 global.tune.maxrewrite = global.tune.bufsize / 2;
553 }
554 else if (!strcmp(args[0], "tune.maxrewrite")) {
555 if (*(args[1]) == 0) {
556 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT | ERR_FATAL;
558 goto out;
559 }
560 global.tune.maxrewrite = atol(args[1]);
561 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
562 global.tune.maxrewrite = global.tune.bufsize / 2;
563 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100564 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
565 if (global.tune.client_rcvbuf != 0) {
566 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT;
568 goto out;
569 }
570 if (*(args[1]) == 0) {
571 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT | ERR_FATAL;
573 goto out;
574 }
575 global.tune.client_rcvbuf = atol(args[1]);
576 }
577 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
578 if (global.tune.server_rcvbuf != 0) {
579 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT;
581 goto out;
582 }
583 if (*(args[1]) == 0) {
584 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588 global.tune.server_rcvbuf = atol(args[1]);
589 }
590 else if (!strcmp(args[0], "tune.sndbuf.client")) {
591 if (global.tune.client_sndbuf != 0) {
592 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT;
594 goto out;
595 }
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
600 }
601 global.tune.client_sndbuf = atol(args[1]);
602 }
603 else if (!strcmp(args[0], "tune.sndbuf.server")) {
604 if (global.tune.server_sndbuf != 0) {
605 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
606 err_code |= ERR_ALERT;
607 goto out;
608 }
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
613 }
614 global.tune.server_sndbuf = atol(args[1]);
615 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616 else if (!strcmp(args[0], "uid")) {
617 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200618 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 err_code |= ERR_ALERT;
620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621 }
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 }
627 global.uid = atol(args[1]);
628 }
629 else if (!strcmp(args[0], "gid")) {
630 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200631 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.gid = atol(args[1]);
641 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200642 /* user/group name handling */
643 else if (!strcmp(args[0], "user")) {
644 struct passwd *ha_user;
645 if (global.uid != 0) {
646 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200647 err_code |= ERR_ALERT;
648 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 errno = 0;
651 ha_user = getpwnam(args[1]);
652 if (ha_user != NULL) {
653 global.uid = (int)ha_user->pw_uid;
654 }
655 else {
656 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 +0200657 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200658 }
659 }
660 else if (!strcmp(args[0], "group")) {
661 struct group *ha_group;
662 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200663 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200664 err_code |= ERR_ALERT;
665 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200666 }
667 errno = 0;
668 ha_group = getgrnam(args[1]);
669 if (ha_group != NULL) {
670 global.gid = (int)ha_group->gr_gid;
671 }
672 else {
673 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 +0200674 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200675 }
676 }
677 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 else if (!strcmp(args[0], "nbproc")) {
679 if (global.nbproc != 0) {
680 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683 }
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 }
689 global.nbproc = atol(args[1]);
690 }
691 else if (!strcmp(args[0], "maxconn")) {
692 if (global.maxconn != 0) {
693 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200694 err_code |= ERR_ALERT;
695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 }
697 if (*(args[1]) == 0) {
698 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 }
702 global.maxconn = atol(args[1]);
703#ifdef SYSTEM_MAXCONN
704 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
705 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);
706 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 }
709#endif /* SYSTEM_MAXCONN */
710 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100711 else if (!strcmp(args[0], "maxpipes")) {
712 if (global.maxpipes != 0) {
713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100716 }
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100721 }
722 global.maxpipes = atol(args[1]);
723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200724 else if (!strcmp(args[0], "ulimit-n")) {
725 if (global.rlimit_nofile != 0) {
726 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200727 err_code |= ERR_ALERT;
728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 }
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 }
735 global.rlimit_nofile = atol(args[1]);
736 }
737 else if (!strcmp(args[0], "chroot")) {
738 if (global.chroot != NULL) {
739 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200740 err_code |= ERR_ALERT;
741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200742 }
743 if (*(args[1]) == 0) {
744 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 }
748 global.chroot = strdup(args[1]);
749 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200750 else if (!strcmp(args[0], "description")) {
751 int i, len=0;
752 char *d;
753
754 if (!*args[1]) {
755 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
756 file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760
761 for(i=1; *args[i]; i++)
762 len += strlen(args[i])+1;
763
764 if (global.desc)
765 free(global.desc);
766
767 global.desc = d = (char *)calloc(1, len);
768
769 d += sprintf(d, "%s", args[1]);
770 for(i=2; *args[i]; i++)
771 d += sprintf(d, " %s", args[i]);
772 }
773 else if (!strcmp(args[0], "node")) {
774 int i;
775 char c;
776
777 for (i=0; args[1][i]; i++) {
778 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100779 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
780 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200781 break;
782 }
783
784 if (!i || args[1][i]) {
785 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
786 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
787 file, linenum, args[0]);
788 err_code |= ERR_ALERT | ERR_FATAL;
789 goto out;
790 }
791
792 if (global.node)
793 free(global.node);
794
795 global.node = strdup(args[1]);
796 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200797 else if (!strcmp(args[0], "pidfile")) {
798 if (global.pidfile != NULL) {
799 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT;
801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802 }
803 if (*(args[1]) == 0) {
804 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT | ERR_FATAL;
806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 }
808 global.pidfile = strdup(args[1]);
809 }
Emeric Bruned760922010-10-22 17:59:25 +0200810 else if (!strcmp(args[0], "unix-bind")) {
811 int cur_arg = 1;
812 while (*(args[cur_arg])) {
813 if (!strcmp(args[cur_arg], "prefix")) {
814 if (global.unix_bind.prefix != NULL) {
815 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
816 err_code |= ERR_ALERT;
817 cur_arg += 2;
818 continue;
819 }
820
821 if (*(args[cur_arg+1]) == 0) {
822 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 global.unix_bind.prefix = strdup(args[cur_arg+1]);
827 cur_arg += 2;
828 continue;
829 }
830
831 if (!strcmp(args[cur_arg], "mode")) {
832
833 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
834 cur_arg += 2;
835 continue;
836 }
837
838 if (!strcmp(args[cur_arg], "uid")) {
839
840 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
841 cur_arg += 2;
842 continue;
843 }
844
845 if (!strcmp(args[cur_arg], "gid")) {
846
847 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
848 cur_arg += 2;
849 continue;
850 }
851
852 if (!strcmp(args[cur_arg], "user")) {
853 struct passwd *user;
854
855 user = getpwnam(args[cur_arg + 1]);
856 if (!user) {
857 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
858 file, linenum, args[0], args[cur_arg + 1 ]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
861 }
862
863 global.unix_bind.ux.uid = user->pw_uid;
864 cur_arg += 2;
865 continue;
866 }
867
868 if (!strcmp(args[cur_arg], "group")) {
869 struct group *group;
870
871 group = getgrnam(args[cur_arg + 1]);
872 if (!group) {
873 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
874 file, linenum, args[0], args[cur_arg + 1 ]);
875 err_code |= ERR_ALERT | ERR_FATAL;
876 goto out;
877 }
878
879 global.unix_bind.ux.gid = group->gr_gid;
880 cur_arg += 2;
881 continue;
882 }
883
884 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
885 file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200890 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100891 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200892 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200893
894 if (*(args[1]) == 0 || *(args[2]) == 0) {
895 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 }
899
900 facility = get_log_facility(args[2]);
901 if (facility < 0) {
902 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT | ERR_FATAL;
904 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 }
906
907 level = 7; /* max syslog level = debug */
908 if (*(args[3])) {
909 level = get_log_level(args[3]);
910 if (level < 0) {
911 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200912 err_code |= ERR_ALERT | ERR_FATAL;
913 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 }
915 }
916
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200917 minlvl = 0; /* limit syslog level to this level (emerg) */
918 if (*(args[4])) {
919 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200920 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200921 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT | ERR_FATAL;
923 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200924 }
925 }
926
Robert Tsai81ae1952007-12-05 10:47:29 +0100927 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100928 struct sockaddr_un *sk = str2sun(args[1]);
929 if (!sk) {
930 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
931 args[1], (int)sizeof(sk->sun_path) - 1);
932 err_code |= ERR_ALERT | ERR_FATAL;
933 goto out;
934 }
935 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100936 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100937 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100938 struct sockaddr_in *sk = str2sa(args[1]);
939 if (!sk) {
940 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943 }
944 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100945 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100946 if (!logsrv.u.in.sin_port)
947 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949
950 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100951 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 global.logfac1 = facility;
953 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200954 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 }
956 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100957 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 global.logfac2 = facility;
959 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200960 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 }
962 else {
963 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200964 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200966 }
967 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
968 if (global.spread_checks != 0) {
969 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200970 err_code |= ERR_ALERT;
971 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200972 }
973 if (*(args[1]) == 0) {
974 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200977 }
978 global.spread_checks = atol(args[1]);
979 if (global.spread_checks < 0 || global.spread_checks > 50) {
980 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200981 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200983 }
984 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200985 struct cfg_kw_list *kwl;
986 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200987 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200988
989 list_for_each_entry(kwl, &cfg_keywords.list, list) {
990 for (index = 0; kwl->kw[index].kw != NULL; index++) {
991 if (kwl->kw[index].section != CFG_GLOBAL)
992 continue;
993 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
994 /* prepare error message just in case */
995 snprintf(trash, sizeof(trash),
996 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200997 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
998 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200999 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001001 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001002 else if (rc > 0) {
1003 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001004 err_code |= ERR_WARN;
1005 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001006 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001008 }
1009 }
1010 }
1011
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001013 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001015
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 out:
1017 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001018}
1019
Willy Tarreau97cb7802010-01-03 20:23:58 +01001020/* Perform the most basic initialization of a proxy :
1021 * memset(), list_init(*), reset_timeouts(*).
1022 */
1023static void init_new_proxy(struct proxy *p)
1024{
1025 memset(p, 0, sizeof(struct proxy));
1026 LIST_INIT(&p->pendconns);
1027 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001028 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001029 LIST_INIT(&p->block_cond);
1030 LIST_INIT(&p->redirect_rules);
1031 LIST_INIT(&p->mon_fail_cond);
1032 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001033 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001034 LIST_INIT(&p->sticking_rules);
1035 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001036 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001037 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001038 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001039 LIST_INIT(&p->req_add);
1040 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001041
1042 /* Timeouts are defined as -1 */
1043 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001044 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001045}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001047void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001049 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 defproxy.mode = PR_MODE_TCP;
1051 defproxy.state = PR_STNEW;
1052 defproxy.maxconn = cfg_maxpconn;
1053 defproxy.conn_retries = CONN_RETRIES;
1054 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001055
1056 defproxy.defsrv.inter = DEF_CHKINTR;
1057 defproxy.defsrv.fastinter = 0;
1058 defproxy.defsrv.downinter = 0;
1059 defproxy.defsrv.rise = DEF_RISETIME;
1060 defproxy.defsrv.fall = DEF_FALLTIME;
1061 defproxy.defsrv.check_port = 0;
1062 defproxy.defsrv.maxqueue = 0;
1063 defproxy.defsrv.minconn = 0;
1064 defproxy.defsrv.maxconn = 0;
1065 defproxy.defsrv.slowstart = 0;
1066 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1067 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1068 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069}
1070
Willy Tarreauade5ec42010-01-28 19:33:49 +01001071
1072static int create_cond_regex_rule(const char *file, int line,
1073 struct proxy *px, int dir, int action, int flags,
1074 const char *cmd, const char *reg, const char *repl,
1075 const char **cond_start)
1076{
1077 regex_t *preg = NULL;
1078 const char *err;
1079 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001080 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001081
1082 if (px == &defproxy) {
1083 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1084 err_code |= ERR_ALERT | ERR_FATAL;
1085 goto err;
1086 }
1087
1088 if (*reg == 0) {
1089 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto err;
1092 }
1093
1094 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1095 err_code |= ERR_WARN;
1096
Willy Tarreau5321c422010-01-28 20:35:13 +01001097 if (cond_start &&
1098 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1099 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1100 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1101 file, line, cmd);
1102 err_code |= ERR_ALERT | ERR_FATAL;
1103 goto err;
1104 }
1105 }
1106 else if (cond_start && **cond_start) {
1107 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1108 file, line, cmd, *cond_start);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto err;
1111 }
1112
1113 if (dir == ACL_DIR_REQ)
1114 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001115 else
1116 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001117
Willy Tarreauade5ec42010-01-28 19:33:49 +01001118 preg = calloc(1, sizeof(regex_t));
1119 if (!preg) {
1120 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1121 err_code = ERR_ALERT | ERR_FATAL;
1122 goto err;
1123 }
1124
1125 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1126 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1127 err_code = ERR_ALERT | ERR_FATAL;
1128 goto err;
1129 }
1130
1131 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001132 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001133 if (repl && err) {
1134 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1135 file, line, cmd, *err);
1136 err_code |= ERR_ALERT | ERR_FATAL;
1137 goto err;
1138 }
1139
1140 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1141 err_code |= ERR_WARN;
1142
1143 return err_code;
1144 err:
1145 free(preg);
1146 return err_code;
1147}
1148
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001150 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001151 * Returns the error code, 0 if OK, or any combination of :
1152 * - ERR_ABORT: must abort ASAP
1153 * - ERR_FATAL: we can continue parsing but not start the service
1154 * - ERR_WARN: a warning has been emitted
1155 * - ERR_ALERT: an alert has been emitted
1156 * Only the two first ones can stop processing, the two others are just
1157 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001159int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160{
1161 static struct proxy *curproxy = NULL;
1162 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001163 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001164 int rc;
1165 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001166 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001167 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168
Willy Tarreau977b8e42006-12-29 14:19:17 +01001169 if (!strcmp(args[0], "listen"))
1170 rc = PR_CAP_LISTEN;
1171 else if (!strcmp(args[0], "frontend"))
1172 rc = PR_CAP_FE | PR_CAP_RS;
1173 else if (!strcmp(args[0], "backend"))
1174 rc = PR_CAP_BE | PR_CAP_RS;
1175 else if (!strcmp(args[0], "ruleset"))
1176 rc = PR_CAP_RS;
1177 else
1178 rc = PR_CAP_NONE;
1179
1180 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001181 if (!*args[1]) {
1182 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1183 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1184 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001185 err_code |= ERR_ALERT | ERR_ABORT;
1186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001187 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001188
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001189 err = invalid_char(args[1]);
1190 if (err) {
1191 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1192 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001193 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001194 }
1195
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001196 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1197 /*
1198 * If there are two proxies with the same name only following
1199 * combinations are allowed:
1200 *
1201 * listen backend frontend ruleset
1202 * listen - - - -
1203 * backend - - OK -
1204 * frontend - OK - -
1205 * ruleset - - - -
1206 */
1207
1208 if (!strcmp(curproxy->id, args[1]) &&
1209 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1210 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001211 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1212 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1213 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001214 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001215 }
1216 }
1217
Willy Tarreaubaaee002006-06-26 02:48:02 +02001218 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1219 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001220 err_code |= ERR_ALERT | ERR_ABORT;
1221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001223
Willy Tarreau97cb7802010-01-03 20:23:58 +01001224 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001225 curproxy->next = proxy;
1226 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001227 curproxy->conf.file = file;
1228 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001229 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001230 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001231 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232
1233 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001234 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001235 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001236 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001237 err_code |= ERR_FATAL;
1238 goto out;
1239 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001240 new = curproxy->listen;
1241 while (new != last) {
1242 new->conf.file = file;
1243 new->conf.line = linenum;
1244 new = new->next;
1245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 global.maxsock++;
1247 }
1248
1249 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001250 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001251 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001252
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001254 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001255 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001256 curproxy->no_options = defproxy.no_options;
1257 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001258 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001259 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001260 curproxy->except_net = defproxy.except_net;
1261 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001262 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001263 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001265 if (defproxy.fwdfor_hdr_len) {
1266 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1267 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1268 }
1269
Willy Tarreaub86db342009-11-30 11:50:16 +01001270 if (defproxy.orgto_hdr_len) {
1271 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1272 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1273 }
1274
Willy Tarreau977b8e42006-12-29 14:19:17 +01001275 if (curproxy->cap & PR_CAP_FE) {
1276 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001277 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001278 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001279
1280 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001281 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1282 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001283
1284 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001286
Willy Tarreau977b8e42006-12-29 14:19:17 +01001287 if (curproxy->cap & PR_CAP_BE) {
1288 curproxy->fullconn = defproxy.fullconn;
1289 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001290
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001291 if (defproxy.check_req) {
1292 curproxy->check_req = calloc(1, defproxy.check_len);
1293 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1294 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001295 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001296
Willy Tarreau977b8e42006-12-29 14:19:17 +01001297 if (defproxy.cookie_name)
1298 curproxy->cookie_name = strdup(defproxy.cookie_name);
1299 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001300 if (defproxy.cookie_domain)
1301 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001302
Willy Tarreau31936852010-10-06 16:59:56 +02001303 if (defproxy.cookie_maxidle)
1304 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1305
1306 if (defproxy.cookie_maxlife)
1307 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1308
Emeric Brun647caf12009-06-30 17:57:00 +02001309 if (defproxy.rdp_cookie_name)
1310 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1311 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1312
Willy Tarreau01732802007-11-01 22:48:15 +01001313 if (defproxy.url_param_name)
1314 curproxy->url_param_name = strdup(defproxy.url_param_name);
1315 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001316
Benoitaffb4812009-03-25 13:02:10 +01001317 if (defproxy.hh_name)
1318 curproxy->hh_name = strdup(defproxy.hh_name);
1319 curproxy->hh_len = defproxy.hh_len;
1320 curproxy->hh_match_domain = defproxy.hh_match_domain;
1321
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001322 if (defproxy.iface_name)
1323 curproxy->iface_name = strdup(defproxy.iface_name);
1324 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001327 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001328 if (defproxy.capture_name)
1329 curproxy->capture_name = strdup(defproxy.capture_name);
1330 curproxy->capture_namelen = defproxy.capture_namelen;
1331 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001333
Willy Tarreau977b8e42006-12-29 14:19:17 +01001334 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001335 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001336 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001337 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001338 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001339 curproxy->uri_auth = defproxy.uri_auth;
1340 curproxy->mon_net = defproxy.mon_net;
1341 curproxy->mon_mask = defproxy.mon_mask;
1342 if (defproxy.monitor_uri)
1343 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1344 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001345 if (defproxy.defbe.name)
1346 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001347 }
1348
1349 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001350 curproxy->timeout.connect = defproxy.timeout.connect;
1351 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001352 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001353 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001354 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001355 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001356 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001357 curproxy->source_addr = defproxy.source_addr;
1358 }
1359
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 curproxy->mode = defproxy.mode;
1361 curproxy->logfac1 = defproxy.logfac1;
1362 curproxy->logsrv1 = defproxy.logsrv1;
1363 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001364 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 curproxy->logfac2 = defproxy.logfac2;
1366 curproxy->logsrv2 = defproxy.logsrv2;
1367 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001368 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001369 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001370 curproxy->conf.used_listener_id = EB_ROOT;
1371 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001372
Willy Tarreau93893792009-07-23 13:19:11 +02001373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 }
1375 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1376 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001377 /* FIXME-20070101: we should do this too at the end of the
1378 * config parsing to free all default values.
1379 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001380 free(defproxy.check_req);
1381 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001382 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001383 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001384 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001385 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001386 free(defproxy.capture_name);
1387 free(defproxy.monitor_uri);
1388 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001389 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001390 free(defproxy.fwdfor_hdr_name);
1391 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001392 free(defproxy.orgto_hdr_name);
1393 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001394
Willy Tarreaua534fea2008-08-03 12:19:50 +02001395 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001396 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001397
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 /* we cannot free uri_auth because it might already be used */
1399 init_default_instance();
1400 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001401 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 }
1404 else if (curproxy == NULL) {
1405 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001406 err_code |= ERR_ALERT | ERR_FATAL;
1407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 }
1409
Willy Tarreau977b8e42006-12-29 14:19:17 +01001410
1411 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001413 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001414 int cur_arg;
1415
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 if (curproxy == &defproxy) {
1417 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001418 err_code |= ERR_ALERT | ERR_FATAL;
1419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001421 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001422 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001423
Emeric Bruned760922010-10-22 17:59:25 +02001424 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001425 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001427 err_code |= ERR_ALERT | ERR_FATAL;
1428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001430
1431 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001432
1433 /* NOTE: the following line might create several listeners if there
1434 * are comma-separated IPs or port ranges. So all further processing
1435 * will have to be applied to all listeners created after last_listen.
1436 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001437 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001438 err_code |= ERR_ALERT | ERR_FATAL;
1439 goto out;
1440 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001441
Willy Tarreau90a570f2009-10-04 20:54:54 +02001442 new_listen = curproxy->listen;
1443 while (new_listen != last_listen) {
1444 new_listen->conf.file = file;
1445 new_listen->conf.line = linenum;
1446 new_listen = new_listen->next;
1447 }
1448
Emeric Bruned760922010-10-22 17:59:25 +02001449 /* Set default global rights and owner for unix bind */
1450 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1451 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1452 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001453 cur_arg = 2;
1454 while (*(args[cur_arg])) {
1455 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1456#ifdef SO_BINDTODEVICE
1457 struct listener *l;
1458
Emeric Bruned760922010-10-22 17:59:25 +02001459 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1460 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1461 file, linenum, args[0], args[cur_arg]);
1462 err_code |= ERR_ALERT | ERR_FATAL;
1463 goto out;
1464 }
1465
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001466 if (!*args[cur_arg + 1]) {
1467 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1468 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001469 err_code |= ERR_ALERT | ERR_FATAL;
1470 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001471 }
1472
1473 for (l = curproxy->listen; l != last_listen; l = l->next)
1474 l->interface = strdup(args[cur_arg + 1]);
1475
1476 global.last_checks |= LSTCHK_NETADM;
1477
1478 cur_arg += 2;
1479 continue;
1480#else
1481 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1482 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001483 err_code |= ERR_ALERT | ERR_FATAL;
1484 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001485#endif
1486 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001487 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1488#ifdef TCP_MAXSEG
1489 struct listener *l;
1490 int mss;
1491
Emeric Bruned760922010-10-22 17:59:25 +02001492 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1493 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1494 file, linenum, args[0], args[cur_arg]);
1495 err_code |= ERR_ALERT | ERR_FATAL;
1496 goto out;
1497 }
1498
Willy Tarreaube1b9182009-06-14 18:48:19 +02001499 if (!*args[cur_arg + 1]) {
1500 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1501 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001502 err_code |= ERR_ALERT | ERR_FATAL;
1503 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001504 }
1505
1506 mss = str2uic(args[cur_arg + 1]);
1507 if (mss < 1 || mss > 65535) {
1508 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1509 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001510 err_code |= ERR_ALERT | ERR_FATAL;
1511 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001512 }
1513
1514 for (l = curproxy->listen; l != last_listen; l = l->next)
1515 l->maxseg = mss;
1516
1517 cur_arg += 2;
1518 continue;
1519#else
1520 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1521 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001524#endif
1525 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001526
1527 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1528#ifdef TCP_DEFER_ACCEPT
1529 struct listener *l;
1530
1531 for (l = curproxy->listen; l != last_listen; l = l->next)
1532 l->options |= LI_O_DEF_ACCEPT;
1533
1534 cur_arg ++;
1535 continue;
1536#else
1537 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1538 file, linenum, args[0], args[cur_arg]);
1539 err_code |= ERR_ALERT | ERR_FATAL;
1540 goto out;
1541#endif
1542 }
1543
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001544 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001545#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001546 struct listener *l;
1547
Emeric Bruned760922010-10-22 17:59:25 +02001548 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1549 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1550 file, linenum, args[0], args[cur_arg]);
1551 err_code |= ERR_ALERT | ERR_FATAL;
1552 goto out;
1553 }
1554
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001555 for (l = curproxy->listen; l != last_listen; l = l->next)
1556 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001557
1558 cur_arg ++;
1559 continue;
1560#else
1561 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1562 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001563 err_code |= ERR_ALERT | ERR_FATAL;
1564 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001565#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001566 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001567
Willy Tarreau8a956912010-10-15 14:27:08 +02001568 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1569 struct listener *l;
1570
1571 for (l = curproxy->listen; l != last_listen; l = l->next)
1572 l->options |= LI_O_ACC_PROXY;
1573
1574 cur_arg ++;
1575 continue;
1576 }
1577
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001578 if (!strcmp(args[cur_arg], "name")) {
1579 struct listener *l;
1580
1581 for (l = curproxy->listen; l != last_listen; l = l->next)
1582 l->name = strdup(args[cur_arg + 1]);
1583
1584 cur_arg += 2;
1585 continue;
1586 }
1587
1588 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001589 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001590 struct listener *l;
1591
1592 if (curproxy->listen->next != last_listen) {
1593 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1594 file, linenum, args[cur_arg]);
1595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
1597 }
1598
1599 if (!*args[cur_arg + 1]) {
1600 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1601 file, linenum, args[cur_arg]);
1602 err_code |= ERR_ALERT | ERR_FATAL;
1603 goto out;
1604 }
1605
1606 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001607 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001608
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001609 if (curproxy->listen->luid <= 0) {
1610 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001611 file, linenum);
1612 err_code |= ERR_ALERT | ERR_FATAL;
1613 goto out;
1614 }
1615
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001616 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1617 if (node) {
1618 l = container_of(node, struct listener, conf.id);
1619 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1620 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
1623 }
1624 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1625
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001626 cur_arg += 2;
1627 continue;
1628 }
1629
Emeric Bruned760922010-10-22 17:59:25 +02001630 if (!strcmp(args[cur_arg], "mode")) {
1631
1632 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1633 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1634 file, linenum, args[0], args[cur_arg]);
1635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
1637 }
1638
1639 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1640
1641 cur_arg += 2;
1642 continue;
1643 }
1644
1645 if (!strcmp(args[cur_arg], "uid")) {
1646
1647 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1648 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1649 file, linenum, args[0], args[cur_arg]);
1650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
1652 }
1653
1654 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1655 cur_arg += 2;
1656 continue;
1657 }
1658
1659 if (!strcmp(args[cur_arg], "gid")) {
1660
1661 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1662 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1663 file, linenum, args[0], args[cur_arg]);
1664 err_code |= ERR_ALERT | ERR_FATAL;
1665 goto out;
1666 }
1667
1668 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1669 cur_arg += 2;
1670 continue;
1671 }
1672
1673 if (!strcmp(args[cur_arg], "user")) {
1674 struct passwd *user;
1675
1676 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1677 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1678 file, linenum, args[0], args[cur_arg]);
1679 err_code |= ERR_ALERT | ERR_FATAL;
1680 goto out;
1681 }
1682 user = getpwnam(args[cur_arg + 1]);
1683 if (!user) {
1684 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1685 file, linenum, args[0], args[cur_arg + 1 ]);
1686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
1688 }
1689
1690 curproxy->listen->perm.ux.uid = user->pw_uid;
1691 cur_arg += 2;
1692 continue;
1693 }
1694
1695 if (!strcmp(args[cur_arg], "group")) {
1696 struct group *group;
1697
1698 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1699 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1700 file, linenum, args[0], args[cur_arg]);
1701 err_code |= ERR_ALERT | ERR_FATAL;
1702 goto out;
1703 }
1704 group = getgrnam(args[cur_arg + 1]);
1705 if (!group) {
1706 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1707 file, linenum, args[0], args[cur_arg + 1 ]);
1708 err_code |= ERR_ALERT | ERR_FATAL;
1709 goto out;
1710 }
1711
1712 curproxy->listen->perm.ux.gid = group->gr_gid;
1713 cur_arg += 2;
1714 continue;
1715 }
1716
Willy Tarreau8a956912010-10-15 14:27:08 +02001717 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 +01001718 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001719 err_code |= ERR_ALERT | ERR_FATAL;
1720 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 }
1725 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1726 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1727 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1728 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001732 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001733 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001734
Willy Tarreaubaaee002006-06-26 02:48:02 +02001735 /* flush useless bits */
1736 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001738 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001739 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001740 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001741 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001742
Willy Tarreau1c47f852006-07-09 08:22:27 +02001743 if (!*args[1]) {
1744 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1745 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001746 err_code |= ERR_ALERT | ERR_FATAL;
1747 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001748 }
1749
Willy Tarreaua534fea2008-08-03 12:19:50 +02001750 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001751 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001752 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001753 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001754 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1755
Willy Tarreau93893792009-07-23 13:19:11 +02001756 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001758 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1759 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1760 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1761 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1762 else {
1763 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766 }
1767 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001768 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001769 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001770
1771 if (curproxy == &defproxy) {
1772 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1773 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001774 err_code |= ERR_ALERT | ERR_FATAL;
1775 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001776 }
1777
1778 if (!*args[1]) {
1779 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1780 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001783 }
1784
1785 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001786 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001787
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001788 if (curproxy->uuid <= 0) {
1789 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001790 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001793 }
1794
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001795 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1796 if (node) {
1797 struct proxy *target = container_of(node, struct proxy, conf.id);
1798 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1799 file, linenum, proxy_type_str(curproxy), curproxy->id,
1800 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
1803 }
1804 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001805 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001806 else if (!strcmp(args[0], "description")) {
1807 int i, len=0;
1808 char *d;
1809
Cyril Bonté99ed3272010-01-24 23:29:44 +01001810 if (curproxy == &defproxy) {
1811 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1812 file, linenum, args[0]);
1813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815 }
1816
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001817 if (!*args[1]) {
1818 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1819 file, linenum, args[0]);
1820 return -1;
1821 }
1822
1823 for(i=1; *args[i]; i++)
1824 len += strlen(args[i])+1;
1825
1826 d = (char *)calloc(1, len);
1827 curproxy->desc = d;
1828
1829 d += sprintf(d, "%s", args[1]);
1830 for(i=2; *args[i]; i++)
1831 d += sprintf(d, " %s", args[i]);
1832
1833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001834 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1835 curproxy->state = PR_STSTOPPED;
1836 }
1837 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1838 curproxy->state = PR_STNEW;
1839 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001840 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1841 int cur_arg = 1;
1842 unsigned int set = 0;
1843
1844 while (*args[cur_arg]) {
1845 int u;
1846 if (strcmp(args[cur_arg], "all") == 0) {
1847 set = 0;
1848 break;
1849 }
1850 else if (strcmp(args[cur_arg], "odd") == 0) {
1851 set |= 0x55555555;
1852 }
1853 else if (strcmp(args[cur_arg], "even") == 0) {
1854 set |= 0xAAAAAAAA;
1855 }
1856 else {
1857 u = str2uic(args[cur_arg]);
1858 if (u < 1 || u > 32) {
1859 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1860 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001861 err_code |= ERR_ALERT | ERR_FATAL;
1862 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001863 }
1864 if (u > global.nbproc) {
1865 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1866 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001867 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001868 }
1869 set |= 1 << (u - 1);
1870 }
1871 cur_arg++;
1872 }
1873 curproxy->bind_proc = set;
1874 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001875 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001876 if (curproxy == &defproxy) {
1877 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001878 err_code |= ERR_ALERT | ERR_FATAL;
1879 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001880 }
1881
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001882 err = invalid_char(args[1]);
1883 if (err) {
1884 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1885 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001886 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001887 }
1888
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001889 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1890 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1891 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001892 err_code |= ERR_ALERT | ERR_FATAL;
1893 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001894 }
1895 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1897 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001900 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001901
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 if (*(args[1]) == 0) {
1903 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1904 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001908
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001909 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001910 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001911 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001912 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001913 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 curproxy->cookie_name = strdup(args[1]);
1915 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001916
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 cur_arg = 2;
1918 while (*(args[cur_arg])) {
1919 if (!strcmp(args[cur_arg], "rewrite")) {
1920 curproxy->options |= PR_O_COOK_RW;
1921 }
1922 else if (!strcmp(args[cur_arg], "indirect")) {
1923 curproxy->options |= PR_O_COOK_IND;
1924 }
1925 else if (!strcmp(args[cur_arg], "insert")) {
1926 curproxy->options |= PR_O_COOK_INS;
1927 }
1928 else if (!strcmp(args[cur_arg], "nocache")) {
1929 curproxy->options |= PR_O_COOK_NOC;
1930 }
1931 else if (!strcmp(args[cur_arg], "postonly")) {
1932 curproxy->options |= PR_O_COOK_POST;
1933 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02001934 else if (!strcmp(args[cur_arg], "preserve")) {
1935 curproxy->options2 |= PR_O2_COOK_PSV;
1936 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 else if (!strcmp(args[cur_arg], "prefix")) {
1938 curproxy->options |= PR_O_COOK_PFX;
1939 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001940 else if (!strcmp(args[cur_arg], "domain")) {
1941 if (!*args[cur_arg + 1]) {
1942 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1943 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001944 err_code |= ERR_ALERT | ERR_FATAL;
1945 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001946 }
1947
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001948 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001949 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001950 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1951 " dots nor does not start with a dot."
1952 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001953 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001954 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001955 }
1956
1957 err = invalid_domainchar(args[cur_arg + 1]);
1958 if (err) {
1959 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1960 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001963 }
1964
Willy Tarreau68a897b2009-12-03 23:28:34 +01001965 if (!curproxy->cookie_domain) {
1966 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1967 } else {
1968 /* one domain was already specified, add another one by
1969 * building the string which will be returned along with
1970 * the cookie.
1971 */
1972 char *new_ptr;
1973 int new_len = strlen(curproxy->cookie_domain) +
1974 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1975 new_ptr = malloc(new_len);
1976 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1977 free(curproxy->cookie_domain);
1978 curproxy->cookie_domain = new_ptr;
1979 }
Willy Tarreau31936852010-10-06 16:59:56 +02001980 cur_arg++;
1981 }
1982 else if (!strcmp(args[cur_arg], "maxidle")) {
1983 unsigned int maxidle;
1984 const char *res;
1985
1986 if (!*args[cur_arg + 1]) {
1987 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
1988 file, linenum, args[cur_arg]);
1989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
1991 }
1992
1993 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
1994 if (res) {
1995 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
1996 file, linenum, *res, args[cur_arg]);
1997 err_code |= ERR_ALERT | ERR_FATAL;
1998 goto out;
1999 }
2000 curproxy->cookie_maxidle = maxidle;
2001 cur_arg++;
2002 }
2003 else if (!strcmp(args[cur_arg], "maxlife")) {
2004 unsigned int maxlife;
2005 const char *res;
2006
2007 if (!*args[cur_arg + 1]) {
2008 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2009 file, linenum, args[cur_arg]);
2010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
2012 }
2013
2014 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2015 if (res) {
2016 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2017 file, linenum, *res, args[cur_arg]);
2018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
2020 }
2021 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002022 cur_arg++;
2023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002025 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 +02002026 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002029 }
2030 cur_arg++;
2031 }
2032 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2033 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2034 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002035 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002036 }
2037
2038 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2039 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2040 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002042 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002043
2044 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2045 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2046 file, linenum);
2047 err_code |= ERR_ALERT | ERR_FATAL;
2048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002050 else if (!strcmp(args[0], "persist")) { /* persist */
2051 if (*(args[1]) == 0) {
2052 Alert("parsing [%s:%d] : missing persist method.\n",
2053 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002054 err_code |= ERR_ALERT | ERR_FATAL;
2055 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002056 }
2057
2058 if (!strncmp(args[1], "rdp-cookie", 10)) {
2059 curproxy->options2 |= PR_O2_RDPC_PRST;
2060
Emeric Brunb982a3d2010-01-04 15:45:53 +01002061 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002062 const char *beg, *end;
2063
2064 beg = args[1] + 11;
2065 end = strchr(beg, ')');
2066
2067 if (!end || end == beg) {
2068 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2069 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002070 err_code |= ERR_ALERT | ERR_FATAL;
2071 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002072 }
2073
2074 free(curproxy->rdp_cookie_name);
2075 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2076 curproxy->rdp_cookie_len = end-beg;
2077 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002078 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002079 free(curproxy->rdp_cookie_name);
2080 curproxy->rdp_cookie_name = strdup("msts");
2081 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2082 }
2083 else { /* syntax */
2084 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2085 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_ALERT | ERR_FATAL;
2087 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002088 }
2089 }
2090 else {
2091 Alert("parsing [%s:%d] : unknown persist method.\n",
2092 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002095 }
2096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002098 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002100 if (curproxy == &defproxy) {
2101 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
2104 }
2105
Willy Tarreau977b8e42006-12-29 14:19:17 +01002106 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002107 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002108
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002110 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002112 err_code |= ERR_ALERT | ERR_FATAL;
2113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 }
2115 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002116 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 curproxy->appsession_name = strdup(args[1]);
2118 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2119 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002120 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2121 if (err) {
2122 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2123 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002124 err_code |= ERR_ALERT | ERR_FATAL;
2125 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002126 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002127 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002128
Willy Tarreau51041c72007-09-09 21:56:53 +02002129 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2130 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_ALERT | ERR_ABORT;
2132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002133 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002134
2135 cur_arg = 6;
2136 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002137 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2138 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002139 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002140 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002141 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002142 } else if (!strcmp(args[cur_arg], "prefix")) {
2143 curproxy->options2 |= PR_O2_AS_PFX;
2144 } else if (!strcmp(args[cur_arg], "mode")) {
2145 if (!*args[cur_arg + 1]) {
2146 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2147 file, linenum, args[0], args[cur_arg]);
2148 err_code |= ERR_ALERT | ERR_FATAL;
2149 goto out;
2150 }
2151
2152 cur_arg++;
2153 if (!strcmp(args[cur_arg], "query-string")) {
2154 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2155 curproxy->options2 |= PR_O2_AS_M_QS;
2156 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2157 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2158 curproxy->options2 |= PR_O2_AS_M_PP;
2159 } else {
2160 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2161 err_code |= ERR_ALERT | ERR_FATAL;
2162 goto out;
2163 }
2164 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002165 cur_arg++;
2166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 } /* Url App Session */
2168 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002169 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002170 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002171
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002173 if (curproxy == &defproxy) {
2174 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178
Willy Tarreaubaaee002006-06-26 02:48:02 +02002179 if (*(args[4]) == 0) {
2180 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2181 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002185 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 curproxy->capture_name = strdup(args[2]);
2187 curproxy->capture_namelen = strlen(curproxy->capture_name);
2188 curproxy->capture_len = atol(args[4]);
2189 if (curproxy->capture_len >= CAPTURE_LEN) {
2190 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2191 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002192 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 curproxy->capture_len = CAPTURE_LEN - 1;
2194 }
2195 curproxy->to_log |= LW_COOKIE;
2196 }
2197 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2198 struct cap_hdr *hdr;
2199
2200 if (curproxy == &defproxy) {
2201 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 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 }
2205
2206 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2207 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2208 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211 }
2212
2213 hdr = calloc(sizeof(struct cap_hdr), 1);
2214 hdr->next = curproxy->req_cap;
2215 hdr->name = strdup(args[3]);
2216 hdr->namelen = strlen(args[3]);
2217 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002218 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 hdr->index = curproxy->nb_req_cap++;
2220 curproxy->req_cap = hdr;
2221 curproxy->to_log |= LW_REQHDR;
2222 }
2223 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2224 struct cap_hdr *hdr;
2225
2226 if (curproxy == &defproxy) {
2227 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 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 }
2231
2232 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2233 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2234 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237 }
2238 hdr = calloc(sizeof(struct cap_hdr), 1);
2239 hdr->next = curproxy->rsp_cap;
2240 hdr->name = strdup(args[3]);
2241 hdr->namelen = strlen(args[3]);
2242 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002243 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 hdr->index = curproxy->nb_rsp_cap++;
2245 curproxy->rsp_cap = hdr;
2246 curproxy->to_log |= LW_RSPHDR;
2247 }
2248 else {
2249 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2250 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 }
2254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002256 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002257 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002258
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 if (*(args[1]) == 0) {
2260 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2261 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 }
2265 curproxy->conn_retries = atol(args[1]);
2266 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002267 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
2268 struct req_acl_rule *req_acl;
2269
2270 if (curproxy == &defproxy) {
2271 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
2274 }
2275
2276
2277 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
2278 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2279 file, linenum, args[0]);
2280 err_code |= ERR_WARN;
2281 }
2282
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002283 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002284
2285 if (!req_acl) {
2286 err_code |= ERR_ALERT | ERR_ABORT;
2287 goto out;
2288 }
2289
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002290 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002291 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
2292 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002293 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002294 if (curproxy == &defproxy) {
2295 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_ALERT | ERR_FATAL;
2297 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002298 }
2299
Willy Tarreauef6494c2010-01-28 17:12:36 +01002300 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002301 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2302 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002305 }
2306
Willy Tarreauef6494c2010-01-28 17:12:36 +01002307 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002308 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2309 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002312 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002313
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002314 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002315 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002316 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002317 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002318 struct redirect_rule *rule;
2319 int cur_arg;
2320 int type = REDIRECT_TYPE_NONE;
2321 int code = 302;
2322 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002323 char *cookie = NULL;
2324 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002325 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002326
Cyril Bonté99ed3272010-01-24 23:29:44 +01002327 if (curproxy == &defproxy) {
2328 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
2331 }
2332
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002333 cur_arg = 1;
2334 while (*(args[cur_arg])) {
2335 if (!strcmp(args[cur_arg], "location")) {
2336 if (!*args[cur_arg + 1]) {
2337 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2338 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002341 }
2342
2343 type = REDIRECT_TYPE_LOCATION;
2344 cur_arg++;
2345 destination = args[cur_arg];
2346 }
2347 else if (!strcmp(args[cur_arg], "prefix")) {
2348 if (!*args[cur_arg + 1]) {
2349 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2350 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002353 }
2354
2355 type = REDIRECT_TYPE_PREFIX;
2356 cur_arg++;
2357 destination = args[cur_arg];
2358 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002359 else if (!strcmp(args[cur_arg], "set-cookie")) {
2360 if (!*args[cur_arg + 1]) {
2361 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2362 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002365 }
2366
2367 cur_arg++;
2368 cookie = args[cur_arg];
2369 cookie_set = 1;
2370 }
2371 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2372 if (!*args[cur_arg + 1]) {
2373 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2374 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002377 }
2378
2379 cur_arg++;
2380 cookie = args[cur_arg];
2381 cookie_set = 0;
2382 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002383 else if (!strcmp(args[cur_arg],"code")) {
2384 if (!*args[cur_arg + 1]) {
2385 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002389 }
2390 cur_arg++;
2391 code = atol(args[cur_arg]);
2392 if (code < 301 || code > 303) {
2393 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2394 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002397 }
2398 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002399 else if (!strcmp(args[cur_arg],"drop-query")) {
2400 flags |= REDIRECT_FLAG_DROP_QS;
2401 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002402 else if (!strcmp(args[cur_arg],"append-slash")) {
2403 flags |= REDIRECT_FLAG_APPEND_SLASH;
2404 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002405 else if (strcmp(args[cur_arg], "if") == 0 ||
2406 strcmp(args[cur_arg], "unless") == 0) {
2407 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2408 if (!cond) {
2409 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2410 file, linenum, args[0]);
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
2413 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002414 break;
2415 }
2416 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002417 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 +02002418 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002421 }
2422 cur_arg++;
2423 }
2424
2425 if (type == REDIRECT_TYPE_NONE) {
2426 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2427 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002430 }
2431
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002432 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2433 rule->cond = cond;
2434 rule->rdr_str = strdup(destination);
2435 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002436 if (cookie) {
2437 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002438 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002439 */
2440 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002441 if (cookie_set) {
2442 rule->cookie_str = malloc(rule->cookie_len + 10);
2443 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2444 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2445 rule->cookie_len += 9;
2446 } else {
2447 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002448 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002449 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2450 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002451 }
2452 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002453 rule->type = type;
2454 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002455 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002456 LIST_INIT(&rule->list);
2457 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002458 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002459 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002460 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002461 struct switching_rule *rule;
2462
Willy Tarreaub099aca2008-10-12 17:26:37 +02002463 if (curproxy == &defproxy) {
2464 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002467 }
2468
Willy Tarreau55ea7572007-06-17 19:56:27 +02002469 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002471
2472 if (*(args[1]) == 0) {
2473 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002476 }
2477
Willy Tarreauef6494c2010-01-28 17:12:36 +01002478 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002479 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2480 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002483 }
2484
Willy Tarreauef6494c2010-01-28 17:12:36 +01002485 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002486 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002487 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002490 }
2491
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002492 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002493
Willy Tarreau55ea7572007-06-17 19:56:27 +02002494 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2495 rule->cond = cond;
2496 rule->be.name = strdup(args[1]);
2497 LIST_INIT(&rule->list);
2498 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2499 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002500 else if ((!strcmp(args[0], "force-persist")) ||
2501 (!strcmp(args[0], "ignore-persist"))) {
2502 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002503
2504 if (curproxy == &defproxy) {
2505 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
2508 }
2509
2510 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2511 err_code |= ERR_WARN;
2512
Willy Tarreauef6494c2010-01-28 17:12:36 +01002513 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002514 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2515 file, linenum, args[0]);
2516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
2518 }
2519
Willy Tarreauef6494c2010-01-28 17:12:36 +01002520 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002521 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2522 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
2525 }
2526
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002527 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002528
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002529 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002530 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002531 if (!strcmp(args[0], "force-persist")) {
2532 rule->type = PERSIST_TYPE_FORCE;
2533 } else {
2534 rule->type = PERSIST_TYPE_IGNORE;
2535 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002536 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002537 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002538 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002539 else if (!strcmp(args[0], "stick-table")) {
2540 int myidx = 1;
2541
2542 curproxy->table.type = (unsigned int)-1;
2543 while (*args[myidx]) {
2544 const char *err;
2545
2546 if (strcmp(args[myidx], "size") == 0) {
2547 myidx++;
2548 if (!*(args[myidx])) {
2549 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2550 file, linenum, args[myidx-1]);
2551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
2553 }
2554 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2555 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2556 file, linenum, *err, args[myidx-1]);
2557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
2559 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002560 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002561 }
2562 else if (strcmp(args[myidx], "expire") == 0) {
2563 myidx++;
2564 if (!*(args[myidx])) {
2565 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2566 file, linenum, args[myidx-1]);
2567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
2569 }
2570 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2571 if (err) {
2572 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2573 file, linenum, *err, args[myidx-1]);
2574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
2576 }
2577 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002578 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002579 }
2580 else if (strcmp(args[myidx], "nopurge") == 0) {
2581 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002582 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002583 }
2584 else if (strcmp(args[myidx], "type") == 0) {
2585 myidx++;
2586 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2587 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2588 file, linenum, args[myidx]);
2589 err_code |= ERR_ALERT | ERR_FATAL;
2590 goto out;
2591 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002592 /* myidx already points to next arg */
2593 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002594 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002595 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002596 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002597
2598 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002599 nw = args[myidx];
2600 while (*nw) {
2601 /* the "store" keyword supports a comma-separated list */
2602 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002603 sa = NULL; /* store arg */
2604 while (*nw && *nw != ',') {
2605 if (*nw == '(') {
2606 *nw = 0;
2607 sa = ++nw;
2608 while (*nw != ')') {
2609 if (!*nw) {
2610 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2611 file, linenum, args[0], cw);
2612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
2614 }
2615 nw++;
2616 }
2617 *nw = '\0';
2618 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002619 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002620 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002621 if (*nw)
2622 *nw++ = '\0';
2623 type = stktable_get_data_type(cw);
2624 if (type < 0) {
2625 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2626 file, linenum, args[0], cw);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
2629 }
Willy Tarreauac782882010-06-20 10:41:54 +02002630
2631 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2632 switch (err) {
2633 case PE_NONE: break;
2634 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002635 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2636 file, linenum, args[0], cw);
2637 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002638 break;
2639
2640 case PE_ARG_MISSING:
2641 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2642 file, linenum, args[0], cw);
2643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
2645
2646 case PE_ARG_NOT_USED:
2647 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2648 file, linenum, args[0], cw);
2649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
2651
2652 default:
2653 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2654 file, linenum, args[0], cw);
2655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002657 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002658 }
2659 myidx++;
2660 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002661 else {
2662 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2663 file, linenum, args[myidx]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002666 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002667 }
2668
2669 if (!curproxy->table.size) {
2670 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2671 file, linenum);
2672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
2674 }
2675
2676 if (curproxy->table.type == (unsigned int)-1) {
2677 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2678 file, linenum);
2679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
2681 }
2682 }
2683 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002684 struct sticking_rule *rule;
2685 struct pattern_expr *expr;
2686 int myidx = 0;
2687 const char *name = NULL;
2688 int flags;
2689
2690 if (curproxy == &defproxy) {
2691 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
2694 }
2695
2696 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2697 err_code |= ERR_WARN;
2698 goto out;
2699 }
2700
2701 myidx++;
2702 if ((strcmp(args[myidx], "store") == 0) ||
2703 (strcmp(args[myidx], "store-request") == 0)) {
2704 myidx++;
2705 flags = STK_IS_STORE;
2706 }
2707 else if (strcmp(args[myidx], "store-response") == 0) {
2708 myidx++;
2709 flags = STK_IS_STORE | STK_ON_RSP;
2710 }
2711 else if (strcmp(args[myidx], "match") == 0) {
2712 myidx++;
2713 flags = STK_IS_MATCH;
2714 }
2715 else if (strcmp(args[myidx], "on") == 0) {
2716 myidx++;
2717 flags = STK_IS_MATCH | STK_IS_STORE;
2718 }
2719 else {
2720 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
2723 }
2724
2725 if (*(args[myidx]) == 0) {
2726 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
2729 }
2730
Emeric Brun485479d2010-09-23 18:02:19 +02002731 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002732 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002733 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
2736 }
2737
2738 if (flags & STK_ON_RSP) {
2739 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2740 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2741 file, linenum, args[0], expr->fetch->kw);
2742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
2744 }
2745 } else {
2746 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2747 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2748 file, linenum, args[0], expr->fetch->kw);
2749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
2751 }
2752 }
2753
2754 if (strcmp(args[myidx], "table") == 0) {
2755 myidx++;
2756 name = args[myidx++];
2757 }
2758
Willy Tarreauef6494c2010-01-28 17:12:36 +01002759 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2760 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002761 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2762 file, linenum, args[0]);
2763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
2765 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002766 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002767 else if (*(args[myidx])) {
2768 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2769 file, linenum, args[0], args[myidx]);
2770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
2772 }
Emeric Brun97679e72010-09-23 17:56:44 +02002773 if (flags & STK_ON_RSP)
2774 err_code |= warnif_cond_requires_req(cond, file, linenum);
2775 else
2776 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002777
Emeric Brunb982a3d2010-01-04 15:45:53 +01002778 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2779 rule->cond = cond;
2780 rule->expr = expr;
2781 rule->flags = flags;
2782 rule->table.name = name ? strdup(name) : NULL;
2783 LIST_INIT(&rule->list);
2784 if (flags & STK_ON_RSP)
2785 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2786 else
2787 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002790 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002792
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2794 curproxy->uri_auth = NULL; /* we must detach from the default config */
2795
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002796 if (!*args[1]) {
2797 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002798 } else if (!strcmp(args[1], "admin")) {
2799 struct stats_admin_rule *rule;
2800
2801 if (curproxy == &defproxy) {
2802 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
2805 }
2806
2807 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2808 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2809 err_code |= ERR_ALERT | ERR_ABORT;
2810 goto out;
2811 }
2812
2813 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2814 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2815 file, linenum, args[0], args[1]);
2816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
2818 }
2819 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2820 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2821 file, linenum, args[0], args[1]);
2822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
2824 }
2825
2826 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2827
2828 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2829 rule->cond = cond;
2830 LIST_INIT(&rule->list);
2831 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 } else if (!strcmp(args[1], "uri")) {
2833 if (*(args[2]) == 0) {
2834 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2838 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_ALERT | ERR_ABORT;
2840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
2842 } else if (!strcmp(args[1], "realm")) {
2843 if (*(args[2]) == 0) {
2844 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2848 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_ABORT;
2850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002852 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002853 unsigned interval;
2854
2855 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2856 if (err) {
2857 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2858 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002861 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2862 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002863 err_code |= ERR_ALERT | ERR_ABORT;
2864 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002865 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002866 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2867 struct req_acl_rule *req_acl;
2868
2869 if (curproxy == &defproxy) {
2870 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874
2875 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2876 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2877 err_code |= ERR_ALERT | ERR_ABORT;
2878 goto out;
2879 }
2880
2881 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2882 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2883 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2884 file, linenum, args[0]);
2885 err_code |= ERR_WARN;
2886 }
2887
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002888 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002889
2890 if (!req_acl) {
2891 err_code |= ERR_ALERT | ERR_ABORT;
2892 goto out;
2893 }
2894
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002895 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002896 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2897
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 } else if (!strcmp(args[1], "auth")) {
2899 if (*(args[2]) == 0) {
2900 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2904 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002905 err_code |= ERR_ALERT | ERR_ABORT;
2906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 }
2908 } else if (!strcmp(args[1], "scope")) {
2909 if (*(args[2]) == 0) {
2910 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2914 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002915 err_code |= ERR_ALERT | ERR_ABORT;
2916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 }
2918 } else if (!strcmp(args[1], "enable")) {
2919 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2920 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_ABORT;
2922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002924 } else if (!strcmp(args[1], "hide-version")) {
2925 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2926 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002927 err_code |= ERR_ALERT | ERR_ABORT;
2928 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002929 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002930 } else if (!strcmp(args[1], "show-legends")) {
2931 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2932 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2933 err_code |= ERR_ALERT | ERR_ABORT;
2934 goto out;
2935 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002936 } else if (!strcmp(args[1], "show-node")) {
2937
2938 if (*args[2]) {
2939 int i;
2940 char c;
2941
2942 for (i=0; args[2][i]; i++) {
2943 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002944 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2945 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002946 break;
2947 }
2948
2949 if (!i || args[2][i]) {
2950 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2951 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2952 file, linenum, args[0], args[1]);
2953 err_code |= ERR_ALERT | ERR_FATAL;
2954 goto out;
2955 }
2956 }
2957
2958 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2959 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2960 err_code |= ERR_ALERT | ERR_ABORT;
2961 goto out;
2962 }
2963 } else if (!strcmp(args[1], "show-desc")) {
2964 char *desc = NULL;
2965
2966 if (*args[2]) {
2967 int i, len=0;
2968 char *d;
2969
2970 for(i=2; *args[i]; i++)
2971 len += strlen(args[i])+1;
2972
2973 desc = d = (char *)calloc(1, len);
2974
2975 d += sprintf(d, "%s", args[2]);
2976 for(i=3; *args[i]; i++)
2977 d += sprintf(d, " %s", args[i]);
2978 }
2979
2980 if (!*args[2] && !global.desc)
2981 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2982 file, linenum, args[1]);
2983 else {
2984 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2985 free(desc);
2986 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2987 err_code |= ERR_ALERT | ERR_ABORT;
2988 goto out;
2989 }
2990 free(desc);
2991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002993stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02002994 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 +01002995 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 }
2999 }
3000 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003001 int optnum;
3002
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003003 if (*(args[1]) == '\0') {
3004 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3005 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003009
3010 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3011 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003012 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3013 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3014 file, linenum, cfg_opts[optnum].name);
3015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
3017 }
Willy Tarreau93893792009-07-23 13:19:11 +02003018 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3019 err_code |= ERR_WARN;
3020 goto out;
3021 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003022
Willy Tarreau3842f002009-06-14 11:39:52 +02003023 curproxy->no_options &= ~cfg_opts[optnum].val;
3024 curproxy->options &= ~cfg_opts[optnum].val;
3025
3026 switch (kwm) {
3027 case KWM_STD:
3028 curproxy->options |= cfg_opts[optnum].val;
3029 break;
3030 case KWM_NO:
3031 curproxy->no_options |= cfg_opts[optnum].val;
3032 break;
3033 case KWM_DEF: /* already cleared */
3034 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003035 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003036
Willy Tarreau93893792009-07-23 13:19:11 +02003037 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003038 }
3039 }
3040
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003041 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3042 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003043 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3044 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3045 file, linenum, cfg_opts2[optnum].name);
3046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
3048 }
Willy Tarreau93893792009-07-23 13:19:11 +02003049 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3050 err_code |= ERR_WARN;
3051 goto out;
3052 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003053
Willy Tarreau3842f002009-06-14 11:39:52 +02003054 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3055 curproxy->options2 &= ~cfg_opts2[optnum].val;
3056
3057 switch (kwm) {
3058 case KWM_STD:
3059 curproxy->options2 |= cfg_opts2[optnum].val;
3060 break;
3061 case KWM_NO:
3062 curproxy->no_options2 |= cfg_opts2[optnum].val;
3063 break;
3064 case KWM_DEF: /* already cleared */
3065 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003066 }
Willy Tarreau93893792009-07-23 13:19:11 +02003067 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003068 }
3069 }
3070
Willy Tarreau3842f002009-06-14 11:39:52 +02003071 if (kwm != KWM_STD) {
3072 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003073 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003076 }
3077
Emeric Brun3a058f32009-06-30 18:26:00 +02003078 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003080 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003082 if (*(args[2]) != '\0') {
3083 if (!strcmp(args[2], "clf")) {
3084 curproxy->options2 |= PR_O2_CLFLOG;
3085 } else {
3086 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003087 err_code |= ERR_ALERT | ERR_FATAL;
3088 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003089 }
3090 }
3091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 else if (!strcmp(args[1], "tcplog"))
3093 /* generate a detailed TCP log */
3094 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 else if (!strcmp(args[1], "tcpka")) {
3096 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003097 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003098 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003099
3100 if (curproxy->cap & PR_CAP_FE)
3101 curproxy->options |= PR_O_TCP_CLI_KA;
3102 if (curproxy->cap & PR_CAP_BE)
3103 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 }
3105 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003106 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003107 err_code |= ERR_WARN;
3108
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003110 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003111 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003112 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003113 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003114 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003115 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003116 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 if (!*args[2]) { /* no argument */
3118 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3119 curproxy->check_len = strlen(DEF_CHECK_REQ);
3120 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003121 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 curproxy->check_req = (char *)malloc(reqlen);
3123 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003124 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003126 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 if (*args[4])
3128 reqlen += strlen(args[4]);
3129 else
3130 reqlen += strlen("HTTP/1.0");
3131
3132 curproxy->check_req = (char *)malloc(reqlen);
3133 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003134 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003136 }
3137 else if (!strcmp(args[1], "ssl-hello-chk")) {
3138 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003139 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003140 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003141
Willy Tarreaua534fea2008-08-03 12:19:50 +02003142 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003143 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003144 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003145 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003146 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003147 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003148 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 }
Willy Tarreau23677902007-05-08 23:50:35 +02003150 else if (!strcmp(args[1], "smtpchk")) {
3151 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003152 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003153 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003154 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003155 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003156 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003157 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003158 curproxy->options |= PR_O_SMTP_CHK;
3159
3160 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3161 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3162 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3163 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3164 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3165 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3166 curproxy->check_req = (char *)malloc(reqlen);
3167 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3168 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3169 } else {
3170 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3171 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3172 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3173 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3174 }
3175 }
3176 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003177 else if (!strcmp(args[1], "mysql-check")) {
3178 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003179 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3180 err_code |= ERR_WARN;
3181
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003182 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003183 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003184 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003185 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003186 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003187 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003188 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003189
3190 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3191 * const char mysql40_client_auth_pkt[] = {
3192 * "\x0e\x00\x00" // packet length
3193 * "\x01" // packet number
3194 * "\x00\x00" // client capabilities
3195 * "\x00\x00\x01" // max packet
3196 * "haproxy\x00" // username (null terminated string)
3197 * "\x00" // filler (always 0x00)
3198 * "\x01\x00\x00" // packet length
3199 * "\x00" // packet number
3200 * "\x01" // COM_QUIT command
3201 * };
3202 */
3203
3204 if (*(args[2])) {
3205 int cur_arg = 2;
3206
3207 while (*(args[cur_arg])) {
3208 if (strcmp(args[cur_arg], "user") == 0) {
3209 char *mysqluser;
3210 int packetlen, reqlen, userlen;
3211
3212 /* suboption header - needs additional argument for it */
3213 if (*(args[cur_arg+1]) == 0) {
3214 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3215 file, linenum, args[0], args[1], args[cur_arg]);
3216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
3218 }
3219 mysqluser = args[cur_arg + 1];
3220 userlen = strlen(mysqluser);
3221 packetlen = userlen + 7;
3222 reqlen = packetlen + 9;
3223
3224 free(curproxy->check_req);
3225 curproxy->check_req = (char *)calloc(1, reqlen);
3226 curproxy->check_len = reqlen;
3227
3228 snprintf(curproxy->check_req, 4, "%c%c%c",
3229 ((unsigned char) packetlen & 0xff),
3230 ((unsigned char) (packetlen >> 8) & 0xff),
3231 ((unsigned char) (packetlen >> 16) & 0xff));
3232
3233 curproxy->check_req[3] = 1;
3234 curproxy->check_req[8] = 1;
3235 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3236 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3237 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3238 cur_arg += 2;
3239 } else {
3240 /* unknown suboption - catchall */
3241 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3242 file, linenum, args[0], args[1]);
3243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
3245 }
3246 } /* end while loop */
3247 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003248 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003249 else if (!strcmp(args[1], "ldap-check")) {
3250 /* use LDAP request to check servers' health */
3251 free(curproxy->check_req);
3252 curproxy->check_req = NULL;
3253 curproxy->options &= ~PR_O_HTTP_CHK;
3254 curproxy->options &= ~PR_O_SMTP_CHK;
3255 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3256 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3257 curproxy->options2 |= PR_O2_LDAP_CHK;
3258
3259 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3260 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3261 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3262 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003263 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003264 int cur_arg;
3265
3266 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3267 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003268 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003269
3270 curproxy->options |= PR_O_FWDFOR;
3271
3272 free(curproxy->fwdfor_hdr_name);
3273 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3274 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3275
3276 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3277 cur_arg = 2;
3278 while (*(args[cur_arg])) {
3279 if (!strcmp(args[cur_arg], "except")) {
3280 /* suboption except - needs additional argument for it */
3281 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3282 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3283 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003286 }
3287 /* flush useless bits */
3288 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003289 cur_arg += 2;
3290 } else if (!strcmp(args[cur_arg], "header")) {
3291 /* suboption header - needs additional argument for it */
3292 if (*(args[cur_arg+1]) == 0) {
3293 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3294 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003297 }
3298 free(curproxy->fwdfor_hdr_name);
3299 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3300 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3301 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003302 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003303 /* unknown suboption - catchall */
3304 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3305 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003308 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003309 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003310 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003311 else if (!strcmp(args[1], "originalto")) {
3312 int cur_arg;
3313
3314 /* insert x-original-to field, but not for the IP address listed as an except.
3315 * set default options (ie: bitfield, header name, etc)
3316 */
3317
3318 curproxy->options |= PR_O_ORGTO;
3319
3320 free(curproxy->orgto_hdr_name);
3321 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3322 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3323
3324 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3325 cur_arg = 2;
3326 while (*(args[cur_arg])) {
3327 if (!strcmp(args[cur_arg], "except")) {
3328 /* suboption except - needs additional argument for it */
3329 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3330 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3331 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003334 }
3335 /* flush useless bits */
3336 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3337 cur_arg += 2;
3338 } else if (!strcmp(args[cur_arg], "header")) {
3339 /* suboption header - needs additional argument for it */
3340 if (*(args[cur_arg+1]) == 0) {
3341 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3342 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003345 }
3346 free(curproxy->orgto_hdr_name);
3347 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3348 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3349 cur_arg += 2;
3350 } else {
3351 /* unknown suboption - catchall */
3352 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3353 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003356 }
3357 } /* end while loop */
3358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 else {
3360 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
Willy Tarreau93893792009-07-23 13:19:11 +02003364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003366 else if (!strcmp(args[0], "default_backend")) {
3367 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003369
3370 if (*(args[1]) == 0) {
3371 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003374 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003375 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003376 curproxy->defbe.name = strdup(args[1]);
3377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003379 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003380 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003381
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003382 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3383 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 /* enable reconnections to dispatch */
3386 curproxy->options |= PR_O_REDISP;
3387 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003388 else if (!strcmp(args[0], "http-check")) {
3389 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003391
3392 if (strcmp(args[1], "disable-on-404") == 0) {
3393 /* enable a graceful server shutdown on an HTTP 404 response */
3394 curproxy->options |= PR_O_DISABLE404;
3395 }
Willy Tarreauef781042010-01-27 11:53:01 +01003396 else if (strcmp(args[1], "send-state") == 0) {
3397 /* enable emission of the apparent state of a server in HTTP checks */
3398 curproxy->options2 |= PR_O2_CHK_SNDST;
3399 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003400 else if (strcmp(args[1], "expect") == 0) {
3401 const char *ptr_arg;
3402 int cur_arg;
3403
3404 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3405 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409
3410 cur_arg = 2;
3411 /* consider exclamation marks, sole or at the beginning of a word */
3412 while (*(ptr_arg = args[cur_arg])) {
3413 while (*ptr_arg == '!') {
3414 curproxy->options2 ^= PR_O2_EXP_INV;
3415 ptr_arg++;
3416 }
3417 if (*ptr_arg)
3418 break;
3419 cur_arg++;
3420 }
3421 /* now ptr_arg points to the beginning of a word past any possible
3422 * exclamation mark, and cur_arg is the argument which holds this word.
3423 */
3424 if (strcmp(ptr_arg, "status") == 0) {
3425 if (!*(args[cur_arg + 1])) {
3426 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3427 file, linenum, args[0], args[1], ptr_arg);
3428 err_code |= ERR_ALERT | ERR_FATAL;
3429 goto out;
3430 }
3431 curproxy->options2 |= PR_O2_EXP_STS;
3432 curproxy->expect_str = strdup(args[cur_arg + 1]);
3433 }
3434 else if (strcmp(ptr_arg, "string") == 0) {
3435 if (!*(args[cur_arg + 1])) {
3436 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3437 file, linenum, args[0], args[1], ptr_arg);
3438 err_code |= ERR_ALERT | ERR_FATAL;
3439 goto out;
3440 }
3441 curproxy->options2 |= PR_O2_EXP_STR;
3442 curproxy->expect_str = strdup(args[cur_arg + 1]);
3443 }
3444 else if (strcmp(ptr_arg, "rstatus") == 0) {
3445 if (!*(args[cur_arg + 1])) {
3446 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3447 file, linenum, args[0], args[1], ptr_arg);
3448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
3450 }
3451 curproxy->options2 |= PR_O2_EXP_RSTS;
3452 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3453 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3454 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3455 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3456 err_code |= ERR_ALERT | ERR_FATAL;
3457 goto out;
3458 }
3459 }
3460 else if (strcmp(ptr_arg, "rstring") == 0) {
3461 if (!*(args[cur_arg + 1])) {
3462 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3463 file, linenum, args[0], args[1], ptr_arg);
3464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
3466 }
3467 curproxy->options2 |= PR_O2_EXP_RSTR;
3468 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3469 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3470 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3471 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
3474 }
3475 }
3476 else {
3477 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3478 file, linenum, args[0], args[1], ptr_arg);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
3482 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003483 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003484 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003487 }
3488 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003489 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003490 if (curproxy == &defproxy) {
3491 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003494 }
3495
Willy Tarreaub80c2302007-11-30 20:51:32 +01003496 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003497 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003498
3499 if (strcmp(args[1], "fail") == 0) {
3500 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003501 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003502 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3503 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003506 }
3507
Willy Tarreauef6494c2010-01-28 17:12:36 +01003508 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003509 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3510 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003513 }
3514 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3515 }
3516 else {
3517 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003520 }
3521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522#ifdef TPROXY
3523 else if (!strcmp(args[0], "transparent")) {
3524 /* enable transparent proxy connections */
3525 curproxy->options |= PR_O_TRANSP;
3526 }
3527#endif
3528 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003529 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003531
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 if (*(args[1]) == 0) {
3533 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 }
3537 curproxy->maxconn = atol(args[1]);
3538 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003539 else if (!strcmp(args[0], "backlog")) { /* backlog */
3540 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003542
3543 if (*(args[1]) == 0) {
3544 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003547 }
3548 curproxy->backlog = atol(args[1]);
3549 }
Willy Tarreau86034312006-12-29 00:10:33 +01003550 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003551 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003553
Willy Tarreau86034312006-12-29 00:10:33 +01003554 if (*(args[1]) == 0) {
3555 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_ALERT | ERR_FATAL;
3557 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003558 }
3559 curproxy->fullconn = atol(args[1]);
3560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3562 if (*(args[1]) == 0) {
3563 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003567 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3568 if (err) {
3569 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3570 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003573 }
3574 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 }
3576 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01003577 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 if (curproxy == &defproxy) {
3579 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003583 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003585
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 if (strchr(args[1], ':') == NULL) {
3587 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003591 sk = str2sa(args[1]);
3592 if (!sk) {
3593 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
3596 }
3597 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 }
3599 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003600 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003602
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003603 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003604 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3605 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003610 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3611 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3612 err_code |= ERR_WARN;
3613
3614 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3615 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3616 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3617 }
3618 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3619 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3620 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3621 }
3622 else {
3623 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
3626 }
3627 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003628 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003630 char *rport, *raddr;
3631 short realport = 0;
3632 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003634 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003639 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641
3642 if (!*args[2]) {
3643 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003648
3649 err = invalid_char(args[1]);
3650 if (err) {
3651 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3652 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003655 }
3656
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003657 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003658 struct sockaddr_in *sk;
3659
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003660 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3661 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3662 err_code |= ERR_ALERT | ERR_ABORT;
3663 goto out;
3664 }
3665
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003666 /* the servers are linked backwards first */
3667 newsrv->next = curproxy->srv;
3668 curproxy->srv = newsrv;
3669 newsrv->proxy = curproxy;
3670 newsrv->conf.file = file;
3671 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003673 LIST_INIT(&newsrv->pendconns);
3674 do_check = 0;
3675 newsrv->state = SRV_RUNNING; /* early server setup */
3676 newsrv->last_change = now.tv_sec;
3677 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003679 /* several ways to check the port component :
3680 * - IP => port=+0, relative
3681 * - IP: => port=+0, relative
3682 * - IP:N => port=N, absolute
3683 * - IP:+N => port=+N, relative
3684 * - IP:-N => port=-N, relative
3685 */
3686 raddr = strdup(args[2]);
3687 rport = strchr(raddr, ':');
3688 if (rport) {
3689 *rport++ = 0;
3690 realport = atol(rport);
3691 if (!isdigit((unsigned char)*rport))
3692 newsrv->state |= SRV_MAPPORTS;
3693 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003695
Willy Tarreaud5191e72010-02-09 20:50:45 +01003696 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003697 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003698 if (!sk) {
3699 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
3702 }
3703 newsrv->addr = *sk;
3704 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003705
3706 newsrv->check_port = curproxy->defsrv.check_port;
3707 newsrv->inter = curproxy->defsrv.inter;
3708 newsrv->fastinter = curproxy->defsrv.fastinter;
3709 newsrv->downinter = curproxy->defsrv.downinter;
3710 newsrv->rise = curproxy->defsrv.rise;
3711 newsrv->fall = curproxy->defsrv.fall;
3712 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3713 newsrv->minconn = curproxy->defsrv.minconn;
3714 newsrv->maxconn = curproxy->defsrv.maxconn;
3715 newsrv->slowstart = curproxy->defsrv.slowstart;
3716 newsrv->onerror = curproxy->defsrv.onerror;
3717 newsrv->consecutive_errors_limit
3718 = curproxy->defsrv.consecutive_errors_limit;
3719 newsrv->uweight = newsrv->iweight
3720 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003722 newsrv->curfd = -1; /* no health-check in progress */
3723 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003725 cur_arg = 3;
3726 } else {
3727 newsrv = &curproxy->defsrv;
3728 cur_arg = 1;
3729 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003730
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003732 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003733 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003734
3735 if (!*args[cur_arg + 1]) {
3736 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3737 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003740 }
3741
3742 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003743 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003744
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003745 if (newsrv->puid <= 0) {
3746 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003747 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003750 }
3751
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003752 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3753 if (node) {
3754 struct server *target = container_of(node, struct server, conf.id);
3755 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3756 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
3759 }
3760 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003761 cur_arg += 2;
3762 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003763 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 newsrv->cookie = strdup(args[cur_arg + 1]);
3765 newsrv->cklen = strlen(args[cur_arg + 1]);
3766 cur_arg += 2;
3767 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003768 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003769 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3770 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3771 cur_arg += 2;
3772 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003774 if (!*args[cur_arg + 1]) {
3775 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3776 file, linenum, args[cur_arg]);
3777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
3779 }
3780
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003782 if (newsrv->rise <= 0) {
3783 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3784 file, linenum, args[cur_arg]);
3785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
3787 }
3788
Willy Tarreau96839092010-03-29 10:02:24 +02003789 if (newsrv->health)
3790 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 cur_arg += 2;
3792 }
3793 else if (!strcmp(args[cur_arg], "fall")) {
3794 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003795
3796 if (!*args[cur_arg + 1]) {
3797 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3798 file, linenum, args[cur_arg]);
3799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
3801 }
3802
3803 if (newsrv->fall <= 0) {
3804 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3805 file, linenum, args[cur_arg]);
3806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
3808 }
3809
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 cur_arg += 2;
3811 }
3812 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003813 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3814 if (err) {
3815 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3816 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003819 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003820 if (val <= 0) {
3821 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3822 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003825 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003826 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 cur_arg += 2;
3828 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003829 else if (!strcmp(args[cur_arg], "fastinter")) {
3830 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3831 if (err) {
3832 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3833 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003836 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003837 if (val <= 0) {
3838 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3839 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003842 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003843 newsrv->fastinter = val;
3844 cur_arg += 2;
3845 }
3846 else if (!strcmp(args[cur_arg], "downinter")) {
3847 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3848 if (err) {
3849 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3850 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003853 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003854 if (val <= 0) {
3855 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3856 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003859 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003860 newsrv->downinter = val;
3861 cur_arg += 2;
3862 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003863 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003864 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3865 if (!sk) {
3866 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
3869 }
3870 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003871 cur_arg += 2;
3872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 else if (!strcmp(args[cur_arg], "port")) {
3874 newsrv->check_port = atol(args[cur_arg + 1]);
3875 cur_arg += 2;
3876 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003877 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003878 newsrv->state |= SRV_BACKUP;
3879 cur_arg ++;
3880 }
3881 else if (!strcmp(args[cur_arg], "weight")) {
3882 int w;
3883 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003884 if (w < 0 || w > 256) {
3885 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003890 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 cur_arg += 2;
3892 }
3893 else if (!strcmp(args[cur_arg], "minconn")) {
3894 newsrv->minconn = atol(args[cur_arg + 1]);
3895 cur_arg += 2;
3896 }
3897 else if (!strcmp(args[cur_arg], "maxconn")) {
3898 newsrv->maxconn = atol(args[cur_arg + 1]);
3899 cur_arg += 2;
3900 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003901 else if (!strcmp(args[cur_arg], "maxqueue")) {
3902 newsrv->maxqueue = atol(args[cur_arg + 1]);
3903 cur_arg += 2;
3904 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003905 else if (!strcmp(args[cur_arg], "slowstart")) {
3906 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003907 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003908 if (err) {
3909 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3910 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003913 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01003914 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01003915 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3916 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003919 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003920 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003921 cur_arg += 2;
3922 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003923 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003924
3925 if (!*args[cur_arg + 1]) {
3926 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3927 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003930 }
3931
3932 newsrv->trackit = strdup(args[cur_arg + 1]);
3933
3934 cur_arg += 2;
3935 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003936 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003937 global.maxsock++;
3938 do_check = 1;
3939 cur_arg += 1;
3940 }
Willy Tarreau96839092010-03-29 10:02:24 +02003941 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
3942 newsrv->state |= SRV_MAINTAIN;
3943 newsrv->state &= ~SRV_RUNNING;
3944 newsrv->health = 0;
3945 cur_arg += 1;
3946 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003947 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003948 if (!strcmp(args[cur_arg + 1], "none"))
3949 newsrv->observe = HANA_OBS_NONE;
3950 else if (!strcmp(args[cur_arg + 1], "layer4"))
3951 newsrv->observe = HANA_OBS_LAYER4;
3952 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3953 if (curproxy->mode != PR_MODE_HTTP) {
3954 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3955 file, linenum, args[cur_arg + 1]);
3956 err_code |= ERR_ALERT;
3957 }
3958 newsrv->observe = HANA_OBS_LAYER7;
3959 }
3960 else {
3961 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02003962 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003963 file, linenum, args[cur_arg], args[cur_arg + 1]);
3964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967
3968 cur_arg += 2;
3969 }
3970 else if (!strcmp(args[cur_arg], "on-error")) {
3971 if (!strcmp(args[cur_arg + 1], "fastinter"))
3972 newsrv->onerror = HANA_ONERR_FASTINTER;
3973 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3974 newsrv->onerror = HANA_ONERR_FAILCHK;
3975 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3976 newsrv->onerror = HANA_ONERR_SUDDTH;
3977 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3978 newsrv->onerror = HANA_ONERR_MARKDWN;
3979 else {
3980 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02003981 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003982 file, linenum, args[cur_arg], args[cur_arg + 1]);
3983 err_code |= ERR_ALERT | ERR_FATAL;
3984 goto out;
3985 }
3986
3987 cur_arg += 2;
3988 }
3989 else if (!strcmp(args[cur_arg], "error-limit")) {
3990 if (!*args[cur_arg + 1]) {
3991 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3992 file, linenum, args[cur_arg]);
3993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 }
3996
3997 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3998
3999 if (newsrv->consecutive_errors_limit <= 0) {
4000 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4001 file, linenum, args[cur_arg]);
4002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
4004 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004005 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004006 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004007 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004008 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004009 struct sockaddr_in *sk;
4010
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004012#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004013 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004014 file, linenum, "source", "usesrc");
4015#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004016 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004017 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004018#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 }
4022 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004023 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4024 if (!sk) {
4025 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
4028 }
4029 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004030
4031 if (port_low != port_high) {
4032 int i;
4033 if (port_low <= 0 || port_low > 65535 ||
4034 port_high <= 0 || port_high > 65535 ||
4035 port_low > port_high) {
4036 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4037 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004040 }
4041 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4042 for (i = 0; i < newsrv->sport_range->size; i++)
4043 newsrv->sport_range->ports[i] = port_low + i;
4044 }
4045
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004047 while (*(args[cur_arg])) {
4048 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004049#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4050#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004051 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4052 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4053 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004056 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004057#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004058 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004059 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004060 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004063 }
4064 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004065 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004066 newsrv->state |= SRV_TPROXY_CLI;
4067 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004068 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004069 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004070 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4071 char *name, *end;
4072
4073 name = args[cur_arg+1] + 7;
4074 while (isspace(*name))
4075 name++;
4076
4077 end = name;
4078 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4079 end++;
4080
4081 newsrv->state &= ~SRV_TPROXY_MASK;
4082 newsrv->state |= SRV_TPROXY_DYN;
4083 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4084 newsrv->bind_hdr_len = end - name;
4085 memcpy(newsrv->bind_hdr_name, name, end - name);
4086 newsrv->bind_hdr_name[end-name] = '\0';
4087 newsrv->bind_hdr_occ = -1;
4088
4089 /* now look for an occurrence number */
4090 while (isspace(*end))
4091 end++;
4092 if (*end == ',') {
4093 end++;
4094 name = end;
4095 if (*end == '-')
4096 end++;
4097 while (isdigit(*end))
4098 end++;
4099 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4100 }
4101
4102 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4103 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4104 " occurrences values smaller than %d.\n",
4105 file, linenum, MAX_HDR_HISTORY);
4106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
4108 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004109 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004110 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4111 if (!sk) {
4112 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
4115 }
4116 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004117 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004118 }
4119 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004120#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004121 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004122#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004123 cur_arg += 2;
4124 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004125#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004126 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004127 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004130#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4131 } /* "usesrc" */
4132
4133 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4134#ifdef SO_BINDTODEVICE
4135 if (!*args[cur_arg + 1]) {
4136 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4137 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004140 }
4141 if (newsrv->iface_name)
4142 free(newsrv->iface_name);
4143
4144 newsrv->iface_name = strdup(args[cur_arg + 1]);
4145 newsrv->iface_len = strlen(newsrv->iface_name);
4146 global.last_checks |= LSTCHK_NETADM;
4147#else
4148 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4149 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004150 err_code |= ERR_ALERT | ERR_FATAL;
4151 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004152#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004153 cur_arg += 2;
4154 continue;
4155 }
4156 /* this keyword in not an option of "source" */
4157 break;
4158 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004160 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004161 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4162 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004165 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004167 if (!defsrv)
Willy Tarreau96839092010-03-29 10:02:24 +02004168 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 +01004169 file, linenum, newsrv->id);
4170 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004171 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 +01004172 file, linenum);
4173
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 }
4177 }
4178
4179 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004180 if (newsrv->trackit) {
4181 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4182 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004185 }
4186
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004187 if (!newsrv->check_port && newsrv->check_addr.sin_port)
4188 newsrv->check_port = newsrv->check_addr.sin_port;
4189
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4191 newsrv->check_port = realport; /* by default */
4192 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004193 /* not yet valid, because no port was set on
4194 * the server either. We'll check if we have
4195 * a known port on the first listener.
4196 */
4197 struct listener *l;
4198 l = curproxy->listen;
4199 if (l) {
4200 int port;
4201 port = (l->addr.ss_family == AF_INET6)
4202 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4203 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4204 newsrv->check_port = port;
4205 }
4206 }
4207 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4209 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004210 err_code |= ERR_ALERT | ERR_FATAL;
4211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004213
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004214 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004215 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004216 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4217 err_code |= ERR_ALERT | ERR_ABORT;
4218 goto out;
4219 }
4220
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004221 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004222 newsrv->state |= SRV_CHECKED;
4223 }
4224
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004225 if (!defsrv) {
4226 if (newsrv->state & SRV_BACKUP)
4227 curproxy->srv_bck++;
4228 else
4229 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004230
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004231 newsrv->prev_state = newsrv->state;
4232 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 }
4234 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004235 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004236 int facility;
4237
4238 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4239 curproxy->logfac1 = global.logfac1;
4240 curproxy->logsrv1 = global.logsrv1;
4241 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004242 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004243 curproxy->logfac2 = global.logfac2;
4244 curproxy->logsrv2 = global.logsrv2;
4245 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004246 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004247 }
4248 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004249 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250
4251 facility = get_log_facility(args[2]);
4252 if (facility < 0) {
4253 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4254 exit(1);
4255 }
4256
4257 level = 7; /* max syslog level = debug */
4258 if (*(args[3])) {
4259 level = get_log_level(args[3]);
4260 if (level < 0) {
4261 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4262 exit(1);
4263 }
4264 }
4265
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004266 minlvl = 0; /* limit syslog level to this level (emerg) */
4267 if (*(args[4])) {
4268 minlvl = get_log_level(args[4]);
4269 if (level < 0) {
4270 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4271 exit(1);
4272 }
4273 }
4274
Robert Tsai81ae1952007-12-05 10:47:29 +01004275 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004276 struct sockaddr_un *sk = str2sun(args[1]);
4277 if (!sk) {
4278 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4279 args[1], (int)sizeof(sk->sun_path) - 1);
4280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
4282 }
4283 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004284 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004285 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004286 struct sockaddr_in *sk = str2sa(args[1]);
4287 if (!sk) {
4288 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4289 err_code |= ERR_ALERT | ERR_FATAL;
4290 goto out;
4291 }
4292 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004293 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004294 if (!logsrv.u.in.sin_port) {
4295 logsrv.u.in.sin_port =
4296 htons(SYSLOG_PORT);
4297 }
4298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004299
4300 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004301 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004302 curproxy->logfac1 = facility;
4303 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004304 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004305 }
4306 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004307 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004308 curproxy->logfac2 = facility;
4309 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004310 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311 }
4312 else {
4313 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_ALERT | ERR_FATAL;
4315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 }
4317 }
4318 else {
4319 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4320 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004323 }
4324 }
4325 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004326 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004327 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004328
Willy Tarreau977b8e42006-12-29 14:19:17 +01004329 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004330 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004331
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004333 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4334 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004337 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004338
4339 /* we must first clear any optional default setting */
4340 curproxy->options &= ~PR_O_TPXY_MASK;
4341 free(curproxy->iface_name);
4342 curproxy->iface_name = NULL;
4343 curproxy->iface_len = 0;
4344
Willy Tarreaud5191e72010-02-09 20:50:45 +01004345 sk = str2sa(args[1]);
4346 if (!sk) {
4347 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4348 err_code |= ERR_ALERT | ERR_FATAL;
4349 goto out;
4350 }
4351 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004352 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004353
4354 cur_arg = 2;
4355 while (*(args[cur_arg])) {
4356 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004357#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4358#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004359 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4360 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4361 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004364 }
4365#endif
4366 if (!*args[cur_arg + 1]) {
4367 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4368 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004371 }
4372
4373 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004374 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004375 curproxy->options |= PR_O_TPXY_CLI;
4376 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004377 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004378 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004379 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4380 char *name, *end;
4381
4382 name = args[cur_arg+1] + 7;
4383 while (isspace(*name))
4384 name++;
4385
4386 end = name;
4387 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4388 end++;
4389
4390 curproxy->options &= ~PR_O_TPXY_MASK;
4391 curproxy->options |= PR_O_TPXY_DYN;
4392 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4393 curproxy->bind_hdr_len = end - name;
4394 memcpy(curproxy->bind_hdr_name, name, end - name);
4395 curproxy->bind_hdr_name[end-name] = '\0';
4396 curproxy->bind_hdr_occ = -1;
4397
4398 /* now look for an occurrence number */
4399 while (isspace(*end))
4400 end++;
4401 if (*end == ',') {
4402 end++;
4403 name = end;
4404 if (*end == '-')
4405 end++;
4406 while (isdigit(*end))
4407 end++;
4408 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4409 }
4410
4411 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4412 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4413 " occurrences values smaller than %d.\n",
4414 file, linenum, MAX_HDR_HISTORY);
4415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
4417 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004418 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004419 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
4420 if (!sk) {
4421 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
4424 }
4425 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004426 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004427 }
4428 global.last_checks |= LSTCHK_NETADM;
4429#if !defined(CONFIG_HAP_LINUX_TPROXY)
4430 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004431#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004432#else /* no TPROXY support */
4433 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004434 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004437#endif
4438 cur_arg += 2;
4439 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004440 }
4441
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004442 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4443#ifdef SO_BINDTODEVICE
4444 if (!*args[cur_arg + 1]) {
4445 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4446 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004447 err_code |= ERR_ALERT | ERR_FATAL;
4448 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004449 }
4450 if (curproxy->iface_name)
4451 free(curproxy->iface_name);
4452
4453 curproxy->iface_name = strdup(args[cur_arg + 1]);
4454 curproxy->iface_len = strlen(curproxy->iface_name);
4455 global.last_checks |= LSTCHK_NETADM;
4456#else
4457 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4458 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004461#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004462 cur_arg += 2;
4463 continue;
4464 }
4465 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4466 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004470 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004471 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4472 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4473 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004477 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004478 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4480 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004481 err_code |= ERR_ALERT | ERR_FATAL;
4482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004483 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004484
4485 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4486 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004487 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004488 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 }
4491 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004492 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4493 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004494 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004495 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 }
4498 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004499 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4500 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004501 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004502 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 }
4505 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004506 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4507 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004508 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004509 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 }
4512 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004513 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4514 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004515 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004516 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004519 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004520 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4521 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004522 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004523 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004524 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004525 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004526 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004527 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4528 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004529 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004530 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004531 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004532 }
4533 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004534 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4535 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004536 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004537 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004538 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004541 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4543 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004544 err_code |= ERR_ALERT | ERR_FATAL;
4545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004546 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004547
4548 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4549 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004550 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004551 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004553 }
4554 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004555 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4556 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004557 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004558 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004560 }
4561 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004562 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4563 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004564 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004565 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567 }
4568 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004569 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4570 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004571 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004572 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 }
4575 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004576 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4577 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004578 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004579 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004582 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004583 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4584 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004585 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004586 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004587 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004590 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004591
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 if (curproxy == &defproxy) {
4593 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004597 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004599
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 if (*(args[1]) == 0) {
4601 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004604 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004605
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004606 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4607 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4608 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4609 file, linenum, args[0]);
4610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
4612 }
4613 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4614 }
4615 else if (*args[2]) {
4616 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4617 file, linenum, args[0], args[2]);
4618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
4620 }
4621
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004622 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004623 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004624 wl->s = strdup(args[1]);
4625 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004626 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004627 }
4628 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004629 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4631 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004635
Willy Tarreauade5ec42010-01-28 19:33:49 +01004636 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4637 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004638 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004639 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 }
4642 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004643 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4644 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004645 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004646 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 }
4649 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004650 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4651 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004652 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004653 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 }
4656 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004657 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004658 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004660 err_code |= ERR_ALERT | ERR_FATAL;
4661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 }
4663
Willy Tarreauade5ec42010-01-28 19:33:49 +01004664 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4665 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004666 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004667 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 }
4670 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004671 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4672 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004673 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004674 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 }
4677 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004678 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4679 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004680 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004681 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 }
4684 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004685 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004686
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 if (curproxy == &defproxy) {
4688 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004691 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004692 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004693 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 if (*(args[1]) == 0) {
4696 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 }
4700
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004701 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4702 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4703 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4704 file, linenum, args[0]);
4705 err_code |= ERR_ALERT | ERR_FATAL;
4706 goto out;
4707 }
4708 err_code |= warnif_cond_requires_req(cond, file, linenum);
4709 }
4710 else if (*args[2]) {
4711 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4712 file, linenum, args[0], args[2]);
4713 err_code |= ERR_ALERT | ERR_FATAL;
4714 goto out;
4715 }
4716
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004717 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004718 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004719 wl->s = strdup(args[1]);
4720 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 }
4722 else if (!strcmp(args[0], "errorloc") ||
4723 !strcmp(args[0], "errorloc302") ||
4724 !strcmp(args[0], "errorloc303")) { /* error location */
4725 int errnum, errlen;
4726 char *err;
4727
Willy Tarreau977b8e42006-12-29 14:19:17 +01004728 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004729 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004730
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004732 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735 }
4736
4737 errnum = atol(args[1]);
4738 if (!strcmp(args[0], "errorloc303")) {
4739 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4740 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4741 } else {
4742 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4743 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4744 }
4745
Willy Tarreau0f772532006-12-23 20:51:41 +01004746 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4747 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004748 chunk_destroy(&curproxy->errmsg[rc]);
4749 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004750 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004753
4754 if (rc >= HTTP_ERR_SIZE) {
4755 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4756 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 free(err);
4758 }
4759 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004760 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4761 int errnum, errlen, fd;
4762 char *err;
4763 struct stat stat;
4764
4765 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004766 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004767
4768 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004769 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004772 }
4773
4774 fd = open(args[2], O_RDONLY);
4775 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4776 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4777 file, linenum, args[2], args[1]);
4778 if (fd >= 0)
4779 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004780 err_code |= ERR_ALERT | ERR_FATAL;
4781 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004782 }
4783
Willy Tarreau27a674e2009-08-17 07:23:33 +02004784 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004785 errlen = stat.st_size;
4786 } else {
4787 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004788 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004789 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004790 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004791 }
4792
4793 err = malloc(errlen); /* malloc() must succeed during parsing */
4794 errnum = read(fd, err, errlen);
4795 if (errnum != errlen) {
4796 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4797 file, linenum, args[2], args[1]);
4798 close(fd);
4799 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004802 }
4803 close(fd);
4804
4805 errnum = atol(args[1]);
4806 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4807 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004808 chunk_destroy(&curproxy->errmsg[rc]);
4809 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004810 break;
4811 }
4812 }
4813
4814 if (rc >= HTTP_ERR_SIZE) {
4815 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4816 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004817 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004818 free(err);
4819 }
4820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004821 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004822 struct cfg_kw_list *kwl;
4823 int index;
4824
4825 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4826 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4827 if (kwl->kw[index].section != CFG_LISTEN)
4828 continue;
4829 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4830 /* prepare error message just in case */
4831 snprintf(trash, sizeof(trash),
4832 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004833 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4834 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004835 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004838 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004839 else if (rc > 0) {
4840 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004841 err_code |= ERR_WARN;
4842 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004843 }
Willy Tarreau93893792009-07-23 13:19:11 +02004844 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004845 }
4846 }
4847 }
4848
Willy Tarreau6daf3432008-01-22 16:44:08 +01004849 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 }
Willy Tarreau93893792009-07-23 13:19:11 +02004853 out:
4854 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855}
4856
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004857int
4858cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4859{
4860
4861 int err_code = 0;
4862 const char *err;
4863
4864 if (!strcmp(args[0], "userlist")) { /* new userlist */
4865 struct userlist *newul;
4866
4867 if (!*args[1]) {
4868 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4869 file, linenum, args[0]);
4870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
4872 }
4873
4874 err = invalid_char(args[1]);
4875 if (err) {
4876 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4877 file, linenum, *err, args[0], args[1]);
4878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
4880 }
4881
4882 for (newul = userlist; newul; newul = newul->next)
4883 if (!strcmp(newul->name, args[1])) {
4884 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4885 file, linenum, args[1]);
4886 err_code |= ERR_WARN;
4887 goto out;
4888 }
4889
4890 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4891 if (!newul) {
4892 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4893 err_code |= ERR_ALERT | ERR_ABORT;
4894 goto out;
4895 }
4896
4897 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4898 newul->name = strdup(args[1]);
4899
4900 if (!newul->groupusers | !newul->name) {
4901 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4902 err_code |= ERR_ALERT | ERR_ABORT;
4903 goto out;
4904 }
4905
4906 newul->next = userlist;
4907 userlist = newul;
4908
4909 } else if (!strcmp(args[0], "group")) { /* new group */
4910 int cur_arg, i;
4911 const char *err;
4912
4913 if (!*args[1]) {
4914 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4915 file, linenum, args[0]);
4916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918 }
4919
4920 err = invalid_char(args[1]);
4921 if (err) {
4922 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4923 file, linenum, *err, args[0], args[1]);
4924 err_code |= ERR_ALERT | ERR_FATAL;
4925 goto out;
4926 }
4927
4928 for(i = 0; i < userlist->grpcnt; i++)
4929 if (!strcmp(userlist->groups[i], args[1])) {
4930 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4931 file, linenum, args[1], userlist->name);
4932 err_code |= ERR_ALERT;
4933 goto out;
4934 }
4935
4936 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4937 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4938 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
4941 }
4942
4943 cur_arg = 2;
4944
4945 while (*args[cur_arg]) {
4946 if (!strcmp(args[cur_arg], "users")) {
4947 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4948 cur_arg += 2;
4949 continue;
4950 } else {
4951 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4952 file, linenum, args[0]);
4953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
4955 }
4956 }
4957
4958 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4959 } else if (!strcmp(args[0], "user")) { /* new user */
4960 struct auth_users *newuser;
4961 int cur_arg;
4962
4963 if (!*args[1]) {
4964 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4965 file, linenum, args[0]);
4966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
4968 }
4969
4970 for (newuser = userlist->users; newuser; newuser = newuser->next)
4971 if (!strcmp(newuser->user, args[1])) {
4972 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4973 file, linenum, args[1], userlist->name);
4974 err_code |= ERR_ALERT;
4975 goto out;
4976 }
4977
4978 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4979 if (!newuser) {
4980 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4981 err_code |= ERR_ALERT | ERR_ABORT;
4982 goto out;
4983 }
4984
4985 newuser->user = strdup(args[1]);
4986
4987 newuser->next = userlist->users;
4988 userlist->users = newuser;
4989
4990 cur_arg = 2;
4991
4992 while (*args[cur_arg]) {
4993 if (!strcmp(args[cur_arg], "password")) {
4994#ifndef CONFIG_HAP_CRYPT
4995 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4996 file, linenum);
4997 err_code |= ERR_ALERT;
4998#endif
4999 newuser->pass = strdup(args[cur_arg + 1]);
5000 cur_arg += 2;
5001 continue;
5002 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5003 newuser->pass = strdup(args[cur_arg + 1]);
5004 newuser->flags |= AU_O_INSECURE;
5005 cur_arg += 2;
5006 continue;
5007 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005008 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005009 cur_arg += 2;
5010 continue;
5011 } else {
5012 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5013 file, linenum, args[0]);
5014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
5016 }
5017 }
5018 } else {
5019 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5020 err_code |= ERR_ALERT | ERR_FATAL;
5021 }
5022
5023out:
5024 return err_code;
5025}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026
5027/*
5028 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005029 * Returns the error code, 0 if OK, or any combination of :
5030 * - ERR_ABORT: must abort ASAP
5031 * - ERR_FATAL: we can continue parsing but not start the service
5032 * - ERR_WARN: a warning has been emitted
5033 * - ERR_ALERT: an alert has been emitted
5034 * Only the two first ones can stop processing, the two others are just
5035 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005036 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005037int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005039 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 FILE *f;
5041 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005042 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005043 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 if ((f=fopen(file,"r")) == NULL)
5046 return -1;
5047
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005048 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005049 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005050 char *end;
5051 char *args[MAX_LINE_ARGS + 1];
5052 char *line = thisline;
5053
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 linenum++;
5055
5056 end = line + strlen(line);
5057
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005058 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5059 /* Check if we reached the limit and the last char is not \n.
5060 * Watch out for the last line without the terminating '\n'!
5061 */
5062 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005063 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005065 }
5066
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005068 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005069 line++;
5070
5071 arg = 0;
5072 args[arg] = line;
5073
5074 while (*line && arg < MAX_LINE_ARGS) {
5075 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5076 * C equivalent value. Other combinations left unchanged (eg: \1).
5077 */
5078 if (*line == '\\') {
5079 int skip = 0;
5080 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5081 *line = line[1];
5082 skip = 1;
5083 }
5084 else if (line[1] == 'r') {
5085 *line = '\r';
5086 skip = 1;
5087 }
5088 else if (line[1] == 'n') {
5089 *line = '\n';
5090 skip = 1;
5091 }
5092 else if (line[1] == 't') {
5093 *line = '\t';
5094 skip = 1;
5095 }
5096 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005097 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 unsigned char hex1, hex2;
5099 hex1 = toupper(line[2]) - '0';
5100 hex2 = toupper(line[3]) - '0';
5101 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5102 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5103 *line = (hex1<<4) + hex2;
5104 skip = 3;
5105 }
5106 else {
5107 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005108 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 }
5110 }
5111 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005112 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 end -= skip;
5114 }
5115 line++;
5116 }
5117 else if (*line == '#' || *line == '\n' || *line == '\r') {
5118 /* end of string, end of loop */
5119 *line = 0;
5120 break;
5121 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005122 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005124 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005125 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 line++;
5127 args[++arg] = line;
5128 }
5129 else {
5130 line++;
5131 }
5132 }
5133
5134 /* empty line */
5135 if (!**args)
5136 continue;
5137
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005138 if (*line) {
5139 /* we had to stop due to too many args.
5140 * Let's terminate the string, print the offending part then cut the
5141 * last arg.
5142 */
5143 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5144 line++;
5145 *line = '\0';
5146
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005147 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005148 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 args[arg] = line;
5151 }
5152
Willy Tarreau540abe42007-05-02 20:50:16 +02005153 /* zero out remaining args and ensure that at least one entry
5154 * is zeroed out.
5155 */
5156 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 args[arg] = line;
5158 }
5159
Willy Tarreau3842f002009-06-14 11:39:52 +02005160 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005161 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005162 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005163 for (arg=0; *args[arg+1]; arg++)
5164 args[arg] = args[arg+1]; // shift args after inversion
5165 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005166 else if (!strcmp(args[0], "default")) {
5167 kwm = KWM_DEF;
5168 for (arg=0; *args[arg+1]; arg++)
5169 args[arg] = args[arg+1]; // shift args after inversion
5170 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005171
Willy Tarreau3842f002009-06-14 11:39:52 +02005172 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5173 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005175 }
5176
Willy Tarreau977b8e42006-12-29 14:19:17 +01005177 if (!strcmp(args[0], "listen") ||
5178 !strcmp(args[0], "frontend") ||
5179 !strcmp(args[0], "backend") ||
5180 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005181 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005183 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005184 cursection = strdup(args[0]);
5185 }
5186 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005188 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005189 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005190 } else if (!strcmp(args[0], "userlist")) {
5191 confsect = CFG_USERLIST;
5192 free(cursection);
5193 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 /* else it's a section keyword */
5196
5197 switch (confsect) {
5198 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005199 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005200 break;
5201 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005202 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005204 case CFG_USERLIST:
5205 err_code |= cfg_parse_users(file, linenum, args, kwm);
5206 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005207 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005208 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005209 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005211
5212 if (err_code & ERR_ABORT)
5213 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005215 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005216 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005218 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005219}
5220
Willy Tarreaubb925012009-07-23 13:36:36 +02005221/*
5222 * Returns the error code, 0 if OK, or any combination of :
5223 * - ERR_ABORT: must abort ASAP
5224 * - ERR_FATAL: we can continue parsing but not start the service
5225 * - ERR_WARN: a warning has been emitted
5226 * - ERR_ALERT: an alert has been emitted
5227 * Only the two first ones can stop processing, the two others are just
5228 * indicators.
5229 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005230int check_config_validity()
5231{
5232 int cfgerr = 0;
5233 struct proxy *curproxy = NULL;
5234 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005235 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005236 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005237 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238
5239 /*
5240 * Now, check for the integrity of all that we have collected.
5241 */
5242
5243 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005244 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005245
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005246 /* first, we will invert the proxy list order */
5247 curproxy = NULL;
5248 while (proxy) {
5249 struct proxy *next;
5250
5251 next = proxy->next;
5252 proxy->next = curproxy;
5253 curproxy = proxy;
5254 if (!next)
5255 break;
5256 proxy = next;
5257 }
5258
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005260 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005261 err_code |= ERR_ALERT | ERR_FATAL;
5262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 }
5264
5265 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005266 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005267 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005268 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005269 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005270 unsigned int next_id;
5271
5272 if (!curproxy->uuid) {
5273 /* proxy ID not set, use automatic numbering with first
5274 * spare entry starting with next_pxid.
5275 */
5276 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5277 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5278 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005279 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005280 next_pxid++;
5281
Willy Tarreau55ea7572007-06-17 19:56:27 +02005282
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005284 /* ensure we don't keep listeners uselessly bound */
5285 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 curproxy = curproxy->next;
5287 continue;
5288 }
5289
Willy Tarreauff01a212009-03-15 13:46:16 +01005290 switch (curproxy->mode) {
5291 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005292 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005293 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005294 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5295 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005296 cfgerr++;
5297 }
5298
5299 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005300 Warning("config : servers will be ignored for %s '%s'.\n",
5301 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005302 break;
5303
5304 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005305 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005306 break;
5307
5308 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005309 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005310 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005311 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5312 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005313 cfgerr++;
5314 }
5315 break;
5316 }
5317
5318 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005319 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5320 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 cfgerr++;
5322 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005323
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005324 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005325 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005326 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005327 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5328 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005329 cfgerr++;
5330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005332 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005333 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5334 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005335 cfgerr++;
5336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005338 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005339 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5340 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005341 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005342 }
5343 }
5344 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
5345 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
5346 /* If no LB algo is set in a backend, and we're not in
5347 * transparent mode, dispatch mode nor proxy mode, we
5348 * want to use balance roundrobin by default.
5349 */
5350 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5351 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 }
5353 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005354
Willy Tarreau82936582007-11-30 15:20:09 +01005355 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5356 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005357 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5358 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005359 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005360 }
5361
Willy Tarreauef781042010-01-27 11:53:01 +01005362 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5363 curproxy->options &= ~PR_O2_CHK_SNDST;
5364 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5365 "send-state", proxy_type_str(curproxy), curproxy->id);
5366 err_code |= ERR_WARN;
5367 }
5368
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005369 /* if a default backend was specified, let's find it */
5370 if (curproxy->defbe.name) {
5371 struct proxy *target;
5372
Alex Williams96532db2009-11-01 21:27:13 -05005373 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005374 if (!target) {
5375 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5376 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005377 cfgerr++;
5378 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005379 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5380 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005381 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005382 } else {
5383 free(curproxy->defbe.name);
5384 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005385 /* we force the backend to be present on at least all of
5386 * the frontend's processes.
5387 */
5388 target->bind_proc = curproxy->bind_proc ?
5389 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 }
5391 }
5392
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005393 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005394 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5395 /* map jump target for ACT_SETBE in req_rep chain */
5396 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005397 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005398 struct proxy *target;
5399
Willy Tarreaua496b602006-12-17 23:15:24 +01005400 if (exp->action != ACT_SETBE)
5401 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005402
Alex Williams96532db2009-11-01 21:27:13 -05005403 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005404 if (!target) {
5405 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5406 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005407 cfgerr++;
5408 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005409 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5410 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005411 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005412 } else {
5413 free((void *)exp->replace);
5414 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005415 /* we force the backend to be present on at least all of
5416 * the frontend's processes.
5417 */
5418 target->bind_proc = curproxy->bind_proc ?
5419 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005420 }
5421 }
5422 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005423
5424 /* find the target proxy for 'use_backend' rules */
5425 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005426 struct proxy *target;
5427
Alex Williams96532db2009-11-01 21:27:13 -05005428 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005429
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005430 if (!target) {
5431 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5432 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005433 cfgerr++;
5434 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005435 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5436 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005437 cfgerr++;
5438 } else {
5439 free((void *)rule->be.name);
5440 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005441 /* we force the backend to be present on at least all of
5442 * the frontend's processes.
5443 */
5444 target->bind_proc = curproxy->bind_proc ?
5445 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005446 }
5447 }
5448
Emeric Brunb982a3d2010-01-04 15:45:53 +01005449 /* find the target table for 'stick' rules */
5450 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5451 struct proxy *target;
5452
Emeric Brun1d33b292010-01-04 15:47:17 +01005453 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5454 if (mrule->flags & STK_IS_STORE)
5455 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5456
Emeric Brunb982a3d2010-01-04 15:45:53 +01005457 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005458 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005459 else
5460 target = curproxy;
5461
5462 if (!target) {
5463 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5464 curproxy->id, mrule->table.name);
5465 cfgerr++;
5466 }
5467 else if (target->table.size == 0) {
5468 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5469 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5470 cfgerr++;
5471 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005472 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005473 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5474 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5475 cfgerr++;
5476 }
5477 else {
5478 free((void *)mrule->table.name);
5479 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005480 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005481 }
5482 }
5483
5484 /* find the target table for 'store response' rules */
5485 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5486 struct proxy *target;
5487
Emeric Brun1d33b292010-01-04 15:47:17 +01005488 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5489
Emeric Brunb982a3d2010-01-04 15:45:53 +01005490 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005491 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005492 else
5493 target = curproxy;
5494
5495 if (!target) {
5496 Alert("Proxy '%s': unable to find store table '%s'.\n",
5497 curproxy->id, mrule->table.name);
5498 cfgerr++;
5499 }
5500 else if (target->table.size == 0) {
5501 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5502 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5503 cfgerr++;
5504 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005505 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005506 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5507 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5508 cfgerr++;
5509 }
5510 else {
5511 free((void *)mrule->table.name);
5512 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005513 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005514 }
5515 }
5516
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005517 /* find the target table for 'tcp-request' layer 4 rules */
5518 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5519 struct proxy *target;
5520
Willy Tarreau56123282010-08-06 19:06:56 +02005521 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005522 continue;
5523
5524 if (trule->act_prm.trk_ctr.table.n)
5525 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5526 else
5527 target = curproxy;
5528
5529 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005530 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5531 curproxy->id, trule->act_prm.trk_ctr.table.n,
5532 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005533 cfgerr++;
5534 }
5535 else if (target->table.size == 0) {
5536 Alert("Proxy '%s': table '%s' used but not configured.\n",
5537 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5538 cfgerr++;
5539 }
5540 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005541 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 +02005542 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5543 cfgerr++;
5544 }
5545 else {
5546 free(trule->act_prm.trk_ctr.table.n);
5547 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005548 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005549 * to pass a list of counters to track and allocate them right here using
5550 * stktable_alloc_data_type().
5551 */
5552 }
5553 }
5554
Willy Tarreaud1f96522010-08-03 19:34:32 +02005555 /* find the target table for 'tcp-request' layer 6 rules */
5556 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5557 struct proxy *target;
5558
Willy Tarreau56123282010-08-06 19:06:56 +02005559 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005560 continue;
5561
5562 if (trule->act_prm.trk_ctr.table.n)
5563 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5564 else
5565 target = curproxy;
5566
5567 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005568 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5569 curproxy->id, trule->act_prm.trk_ctr.table.n,
5570 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005571 cfgerr++;
5572 }
5573 else if (target->table.size == 0) {
5574 Alert("Proxy '%s': table '%s' used but not configured.\n",
5575 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5576 cfgerr++;
5577 }
5578 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005579 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 +02005580 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5581 cfgerr++;
5582 }
5583 else {
5584 free(trule->act_prm.trk_ctr.table.n);
5585 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005586 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005587 * to pass a list of counters to track and allocate them right here using
5588 * stktable_alloc_data_type().
5589 */
5590 }
5591 }
5592
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005593 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
5594 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005595 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5596 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5597 "proxy", curproxy->id);
5598 cfgerr++;
5599 goto out_uri_auth_compat;
5600 }
5601
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005602 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005603 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005604 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005605 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005606
Willy Tarreau95fa4692010-02-01 13:05:50 +01005607 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5608 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005609
5610 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005611 uri_auth_compat_req[i++] = "realm";
5612 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5613 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005614
Willy Tarreau95fa4692010-02-01 13:05:50 +01005615 uri_auth_compat_req[i++] = "unless";
5616 uri_auth_compat_req[i++] = "{";
5617 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5618 uri_auth_compat_req[i++] = "}";
5619 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005620
Willy Tarreau95fa4692010-02-01 13:05:50 +01005621 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5622 if (!req_acl) {
5623 cfgerr++;
5624 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005625 }
5626
Willy Tarreau95fa4692010-02-01 13:05:50 +01005627 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
5628
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005629 if (curproxy->uri_auth->auth_realm) {
5630 free(curproxy->uri_auth->auth_realm);
5631 curproxy->uri_auth->auth_realm = NULL;
5632 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005633
5634 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005635 }
5636out_uri_auth_compat:
5637
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005638 cfgerr += acl_find_targets(curproxy);
5639
Willy Tarreau2738a142006-07-08 17:28:09 +02005640 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005641 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005642 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005643 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005644 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005645 " | While not properly invalid, you will certainly encounter various problems\n"
5646 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005647 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005648 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005649 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005650 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005651
Willy Tarreau1fa31262007-12-03 00:36:16 +01005652 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5653 * We must still support older configurations, so let's find out whether those
5654 * parameters have been set or must be copied from contimeouts.
5655 */
5656 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005657 if (!curproxy->timeout.tarpit ||
5658 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005659 /* tarpit timeout not set. We search in the following order:
5660 * default.tarpit, curr.connect, default.connect.
5661 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005662 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005663 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005664 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005665 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005666 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005667 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005668 }
5669 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005670 (!curproxy->timeout.queue ||
5671 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005672 /* queue timeout not set. We search in the following order:
5673 * default.queue, curr.connect, default.connect.
5674 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005675 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005676 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005677 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005678 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005679 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005680 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005681 }
5682 }
5683
Willy Tarreau07a54902010-03-29 18:33:29 +02005684 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005685 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5686 curproxy->check_req = (char *)malloc(curproxy->check_len);
5687 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005688 }
5689
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005690 /* The small pools required for the capture lists */
5691 if (curproxy->nb_req_cap)
5692 curproxy->req_cap_pool = create_pool("ptrcap",
5693 curproxy->nb_req_cap * sizeof(char *),
5694 MEM_F_SHARED);
5695 if (curproxy->nb_rsp_cap)
5696 curproxy->rsp_cap_pool = create_pool("ptrcap",
5697 curproxy->nb_rsp_cap * sizeof(char *),
5698 MEM_F_SHARED);
5699
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005700 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5701 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5702 MEM_F_SHARED);
5703
Willy Tarreau86034312006-12-29 00:10:33 +01005704 /* for backwards compatibility with "listen" instances, if
5705 * fullconn is not set but maxconn is set, then maxconn
5706 * is used.
5707 */
5708 if (!curproxy->fullconn)
5709 curproxy->fullconn = curproxy->maxconn;
5710
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 /* first, we will invert the servers list order */
5712 newsrv = NULL;
5713 while (curproxy->srv) {
5714 struct server *next;
5715
5716 next = curproxy->srv->next;
5717 curproxy->srv->next = newsrv;
5718 newsrv = curproxy->srv;
5719 if (!next)
5720 break;
5721 curproxy->srv = next;
5722 }
5723
Willy Tarreaudd701652010-05-25 23:03:02 +02005724 /* assign automatic UIDs to servers which don't have one yet */
5725 next_id = 1;
5726 newsrv = curproxy->srv;
5727 while (newsrv != NULL) {
5728 if (!newsrv->puid) {
5729 /* server ID not set, use automatic numbering with first
5730 * spare entry starting with next_svid.
5731 */
5732 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5733 newsrv->conf.id.key = newsrv->puid = next_id;
5734 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
5735 }
5736 next_id++;
5737 newsrv = newsrv->next;
5738 }
5739
Willy Tarreau20697042007-11-15 23:26:18 +01005740 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01005741 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005743 /* We have to initialize the server lookup mechanism depending
5744 * on what LB algorithm was choosen.
5745 */
5746
5747 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
5748 switch (curproxy->lbprm.algo & BE_LB_KIND) {
5749 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02005750 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
5751 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5752 init_server_map(curproxy);
5753 } else {
5754 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
5755 fwrr_init_server_groups(curproxy);
5756 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005757 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005758
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005759 case BE_LB_KIND_LC:
5760 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01005761 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005762 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005763
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005764 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005765 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
5766 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
5767 chash_init_server_tree(curproxy);
5768 } else {
5769 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
5770 init_server_map(curproxy);
5771 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005772 break;
5773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774
5775 if (curproxy->options & PR_O_LOGASAP)
5776 curproxy->to_log &= ~LW_BYTES;
5777
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02005778 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
5779 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
5780 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
5781 proxy_type_str(curproxy), curproxy->id);
5782 err_code |= ERR_WARN;
5783 }
5784
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005785 if (curproxy->mode != PR_MODE_HTTP) {
5786 int optnum;
5787
5788 if (curproxy->options & PR_O_COOK_ANY) {
5789 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
5790 proxy_type_str(curproxy), curproxy->id);
5791 err_code |= ERR_WARN;
5792 }
5793
5794 if (curproxy->uri_auth) {
5795 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
5796 proxy_type_str(curproxy), curproxy->id);
5797 err_code |= ERR_WARN;
5798 curproxy->uri_auth = NULL;
5799 }
5800
5801 if (curproxy->options & PR_O_FWDFOR) {
5802 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5803 "forwardfor", proxy_type_str(curproxy), curproxy->id);
5804 err_code |= ERR_WARN;
5805 curproxy->options &= ~PR_O_FWDFOR;
5806 }
5807
5808 if (curproxy->options & PR_O_ORGTO) {
5809 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5810 "originalto", proxy_type_str(curproxy), curproxy->id);
5811 err_code |= ERR_WARN;
5812 curproxy->options &= ~PR_O_ORGTO;
5813 }
5814
5815 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
5816 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
5817 (curproxy->cap & cfg_opts[optnum].cap) &&
5818 (curproxy->options & cfg_opts[optnum].val)) {
5819 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5820 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
5821 err_code |= ERR_WARN;
5822 curproxy->options &= ~cfg_opts[optnum].val;
5823 }
5824 }
5825
5826 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
5827 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
5828 (curproxy->cap & cfg_opts2[optnum].cap) &&
5829 (curproxy->options2 & cfg_opts2[optnum].val)) {
5830 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
5831 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
5832 err_code |= ERR_WARN;
5833 curproxy->options2 &= ~cfg_opts2[optnum].val;
5834 }
5835 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005836
Willy Tarreauefa5f512010-03-30 20:13:29 +02005837#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005838 if (curproxy->bind_hdr_occ) {
5839 curproxy->bind_hdr_occ = 0;
5840 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
5841 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
5842 err_code |= ERR_WARN;
5843 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005844#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01005845 }
5846
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01005848 * ensure that we're not cross-dressing a TCP server into HTTP.
5849 */
5850 newsrv = curproxy->srv;
5851 while (newsrv != NULL) {
5852 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005853 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5854 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005855 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005856 }
Willy Tarreaubce70882009-09-07 11:51:47 +02005857
Willy Tarreauefa5f512010-03-30 20:13:29 +02005858#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02005859 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
5860 newsrv->bind_hdr_occ = 0;
5861 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
5862 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
5863 err_code |= ERR_WARN;
5864 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02005865#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01005866 newsrv = newsrv->next;
5867 }
5868
5869 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 * If this server supports a maxconn parameter, it needs a dedicated
5871 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005872 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 */
5874 newsrv = curproxy->srv;
5875 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005876 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877 /* Only 'minconn' was specified, or it was higher than or equal
5878 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5879 * this will avoid further useless expensive computations.
5880 */
5881 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005882 } else if (newsrv->maxconn && !newsrv->minconn) {
5883 /* minconn was not specified, so we set it to maxconn */
5884 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005885 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005886 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5887 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005888 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 }
5890
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005891 if (newsrv->trackit) {
5892 struct proxy *px;
5893 struct server *srv;
5894 char *pname, *sname;
5895
5896 pname = newsrv->trackit;
5897 sname = strrchr(pname, '/');
5898
5899 if (sname)
5900 *sname++ = '\0';
5901 else {
5902 sname = pname;
5903 pname = NULL;
5904 }
5905
5906 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005907 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005908 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005909 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5910 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005911 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005912 cfgerr++;
5913 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005914 }
5915 } else
5916 px = curproxy;
5917
5918 srv = findserver(px, sname);
5919 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005920 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5921 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005922 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005923 cfgerr++;
5924 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005925 }
5926
5927 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005928 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005929 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005930 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005931 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005932 cfgerr++;
5933 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005934 }
5935
5936 if (curproxy != px &&
5937 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005938 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005939 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005940 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005941 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005942 cfgerr++;
5943 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005944 }
5945
5946 newsrv->tracked = srv;
5947 newsrv->tracknext = srv->tracknext;
5948 srv->tracknext = newsrv;
5949
5950 free(newsrv->trackit);
5951 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005952 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005953 newsrv = newsrv->next;
5954 }
5955
Willy Tarreauc1a21672009-08-16 22:37:44 +02005956 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02005957 curproxy->accept = frontend_accept;
5958
Willy Tarreauc1a21672009-08-16 22:37:44 +02005959 if (curproxy->tcp_req.inspect_delay ||
5960 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02005961 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005962
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005963 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005964 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005965 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005966 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005967
5968 /* both TCP and HTTP must check switching rules */
5969 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5970 }
5971
5972 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02005973 if (curproxy->tcp_req.inspect_delay ||
5974 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5975 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
5976
Emeric Brun97679e72010-09-23 17:56:44 +02005977 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
5978 curproxy->be_rsp_ana |= AN_RES_INSPECT;
5979
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005980 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005981 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005982 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005983 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005984
5985 /* If the backend does requires RDP cookie persistence, we have to
5986 * enable the corresponding analyser.
5987 */
5988 if (curproxy->options2 & PR_O2_RDPC_PRST)
5989 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5990 }
5991
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005992 listener = NULL;
5993 while (curproxy->listen) {
5994 struct listener *next;
5995
5996 next = curproxy->listen->next;
5997 curproxy->listen->next = listener;
5998 listener = curproxy->listen;
5999
6000 if (!next)
6001 break;
6002
6003 curproxy->listen = next;
6004 }
6005
Willy Tarreaue6b98942007-10-29 01:09:36 +01006006 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006007 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006008 listener = curproxy->listen;
6009 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006010 if (!listener->luid) {
6011 /* listener ID not set, use automatic numbering with first
6012 * spare entry starting with next_luid.
6013 */
6014 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6015 listener->conf.id.key = listener->luid = next_id;
6016 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006017 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006018 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006019
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006020 /* enable separate counters */
6021 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6022 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6023 if (!listener->name) {
6024 sprintf(trash, "sock-%d", listener->luid);
6025 listener->name = strdup(trash);
6026 }
6027 }
6028
Willy Tarreaue6b98942007-10-29 01:09:36 +01006029 if (curproxy->options & PR_O_TCP_NOLING)
6030 listener->options |= LI_O_NOLINGER;
6031 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006032 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006033 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006034 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006035 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006036 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006037 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006038
Willy Tarreau8a956912010-10-15 14:27:08 +02006039 if (listener->options & LI_O_ACC_PROXY)
6040 listener->analysers |= AN_REQ_DECODE_PROXY;
6041
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006042 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6043 listener->options |= LI_O_TCP_RULES;
6044
Willy Tarreaude3041d2010-05-31 10:56:17 +02006045 if (curproxy->mon_mask.s_addr)
6046 listener->options |= LI_O_CHK_MONNET;
6047
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006048 /* smart accept mode is automatic in HTTP mode */
6049 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6050 (curproxy->mode == PR_MODE_HTTP &&
6051 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6052 listener->options |= LI_O_NOQUICKACK;
6053
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006054 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006055 listener = listener->next;
6056 }
6057
Willy Tarreaubaaee002006-06-26 02:48:02 +02006058 curproxy = curproxy->next;
6059 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006060
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006061 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6062 struct auth_users *curuser;
6063 int g;
6064
6065 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6066 unsigned int group_mask = 0;
6067 char *group = NULL;
6068
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006069 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006070 continue;
6071
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006072 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006073
6074 for (g = 0; g < curuserlist->grpcnt; g++)
6075 if (!strcmp(curuserlist->groups[g], group))
6076 break;
6077
6078 if (g == curuserlist->grpcnt) {
6079 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6080 curuserlist->name, group, curuser->user);
6081 err_code |= ERR_ALERT | ERR_FATAL;
6082 goto out;
6083 }
6084
6085 group_mask |= (1 << g);
6086 }
6087
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006088 free(curuser->u.groups);
6089 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006090 }
6091
6092 for (g = 0; g < curuserlist->grpcnt; g++) {
6093 char *user = NULL;
6094
6095 if (!curuserlist->groupusers[g])
6096 continue;
6097
6098 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6099 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6100 if (!strcmp(curuser->user, user))
6101 break;
6102
6103 if (!curuser) {
6104 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6105 curuserlist->name, user, curuserlist->groups[g]);
6106 err_code |= ERR_ALERT | ERR_FATAL;
6107 goto out;
6108 }
6109
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006110 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006111 }
6112
6113 free(curuserlist->groupusers[g]);
6114 }
6115
6116 free(curuserlist->groupusers);
6117
6118#ifdef DEBUG_AUTH
6119 for (g = 0; g < curuserlist->grpcnt; g++) {
6120 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6121
6122 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6123 if (curuser->group_mask & (1 << g))
6124 fprintf(stderr, " %s", curuser->user);
6125 }
6126
6127 fprintf(stderr, "\n");
6128 }
6129#endif
6130
6131 }
6132
Willy Tarreau056f5682010-06-06 15:51:11 +02006133 /* initialize stick-tables on backend capable proxies. This must not
6134 * be done earlier because the data size may be discovered while parsing
6135 * other proxies.
6136 */
6137 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006138 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006139
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006140 /*
6141 * Recount currently required checks.
6142 */
6143
6144 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6145 int optnum;
6146
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006147 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6148 if (curproxy->options & cfg_opts[optnum].val)
6149 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006150
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006151 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6152 if (curproxy->options2 & cfg_opts2[optnum].val)
6153 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006154 }
6155
Willy Tarreaubb925012009-07-23 13:36:36 +02006156 if (cfgerr > 0)
6157 err_code |= ERR_ALERT | ERR_FATAL;
6158 out:
6159 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160}
6161
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006162/*
6163 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6164 * parsing sessions.
6165 */
6166void cfg_register_keywords(struct cfg_kw_list *kwl)
6167{
6168 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6169}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006171/*
6172 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6173 */
6174void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6175{
6176 LIST_DEL(&kwl->list);
6177 LIST_INIT(&kwl->list);
6178}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179
6180/*
6181 * Local variables:
6182 * c-indent-level: 8
6183 * c-basic-offset: 8
6184 * End:
6185 */