blob: e4ee9a052250f5f4d3a284f902b0672916b3de84 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020047#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010049#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020050#include <proto/lb_fwlc.h>
51#include <proto/lb_fwrr.h>
52#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020061#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010063#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010065#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066
67
Willy Tarreauf3c69202006-07-09 16:42:34 +020068/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
69 * ssl-hello-chk option to ensure that the remote server speaks SSL.
70 *
71 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
72 */
73const char sslv3_client_hello_pkt[] = {
74 "\x16" /* ContentType : 0x16 = Hanshake */
75 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
76 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
77 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
78 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
79 "\x03\x00" /* Hello Version : 0x0300 = v3 */
80 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
81 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
82 "\x00" /* Session ID length : empty (no session ID) */
83 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
84 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
85 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
86 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
87 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
88 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
89 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
90 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
91 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
92 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
93 "\x00\x38" "\x00\x39" "\x00\x3A"
94 "\x01" /* Compression Length : 0x01 = 1 byte for types */
95 "\x00" /* Compression Type : 0x00 = NULL compression */
96};
97
Willy Tarreau3842f002009-06-14 11:39:52 +020098/* various keyword modifiers */
99enum kw_mod {
100 KWM_STD = 0, /* normal */
101 KWM_NO, /* "no" prefixed before the keyword */
102 KWM_DEF, /* "default" prefixed before the keyword */
103};
104
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100106struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100107 const char *name;
108 unsigned int val;
109 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100111 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112};
113
114/* proxy->options */
115static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
118 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
119 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
120 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
121 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
122 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
123 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
127 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
128 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
129 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
130 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
131 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
132 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100133#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100134 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100135#else
136 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100137#endif
138
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100139 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140};
141
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142/* proxy->options2 */
143static const struct cfg_opt cfg_opts2[] =
144{
145#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100146 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
148 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100149#else
150 { "splice-request", 0, 0, 0, 0 },
151 { "splice-response", 0, 0, 0, 0 },
152 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100153#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
155 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
156 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
157 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
158 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
159 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
161 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
162 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
163 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200164 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200165 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100166 { NULL, 0, 0, 0 }
167};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168
Willy Tarreau6daf3432008-01-22 16:44:08 +0100169static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
171int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100172int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200174/* List head of all known configuration keywords */
175static struct cfg_kw_list cfg_keywords = {
176 .list = LIST_HEAD_INIT(cfg_keywords.list)
177};
178
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179/*
180 * converts <str> to a list of listeners which are dynamically allocated.
181 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
182 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
183 * - <port> is a numerical port from 1 to 65535 ;
184 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
185 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200186 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100188static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189{
190 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100191 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200192 int port, end;
193
194 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200195
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 while (next && *next) {
197 struct sockaddr_storage ss;
198
199 str = next;
200 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100201 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202 *next++ = 0;
203 }
204
Emeric Bruned760922010-10-22 17:59:25 +0200205 if (*str == '/') {
206 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
207 /* so compute max path */
208 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
209 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 +0200210
Emeric Bruned760922010-10-22 17:59:25 +0200211 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100212 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
213 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200214 goto fail;
215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200218 ss.ss_family = AF_UNIX;
219 if (global.unix_bind.prefix) {
220 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
221 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 }
Emeric Bruned760922010-10-22 17:59:25 +0200223 else {
224 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
225 }
226 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 }
228 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100231 ss2 = str2sa_range(str, &port, &end);
232 if (!ss2) {
233 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
234 file, line, str);
235 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100238 if (!port) {
239 Alert("parsing [%s:%d] : missing port number: '%s'\n",
240 file, line, str);
241 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 /* OK the address looks correct */
245 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Emeric Bruned760922010-10-22 17:59:25 +0200247 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
249 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200250 goto fail;
251 }
252
253 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100254 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
255 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200256 goto fail;
257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200258 }
259
260 for (; port <= end; port++) {
261 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200262 l->next = curproxy->listen;
263 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264
265 l->fd = -1;
266 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 l->state = LI_INIT;
268
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100269 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100271 tcpv4_add_listener(l);
272 }
Emeric Bruned760922010-10-22 17:59:25 +0200273 else if (ss.ss_family == AF_INET6) {
274 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
275 tcpv6_add_listener(l);
276 }
277 else {
278 l->perm.ux.gid = l->perm.ux.uid = -1;
279 l->perm.ux.mode = 0;
280 uxst_add_listener(l);
281 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200282
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200283 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100284 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 } /* end for(port) */
286 } /* end while(next) */
287 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200288 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 fail:
290 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292}
293
Willy Tarreau977b8e42006-12-29 14:19:17 +0100294/*
295 * Sends a warning if proxy <proxy> does not have at least one of the
296 * capabilities in <cap>. An optionnal <hint> may be added at the end
297 * of the warning to help the user. Returns 1 if a warning was emitted
298 * or 0 if the condition is valid.
299 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100300int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100301{
302 char *msg;
303
304 switch (cap) {
305 case PR_CAP_BE: msg = "no backend"; break;
306 case PR_CAP_FE: msg = "no frontend"; break;
307 case PR_CAP_RS: msg = "no ruleset"; break;
308 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
309 default: msg = "not enough"; break;
310 }
311
312 if (!(proxy->cap & cap)) {
313 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100314 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100315 return 1;
316 }
317 return 0;
318}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319
Willy Tarreau61d18892009-03-31 10:49:21 +0200320/* Report a warning if a rule is placed after a 'block' rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100323int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200324{
325 if (!LIST_ISEMPTY(&proxy->block_cond)) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
333/* Report a warning if a rule is placed after a reqrewrite rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100336int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200337{
338 if (proxy->req_exp) {
339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
346/* Report a warning if a rule is placed after a reqadd rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100351 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a redirect rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a 'use_backend' rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
377 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
389 warnif_rule_after_reqadd(proxy, file, line, arg) ||
390 warnif_rule_after_redirect(proxy, file, line, arg) ||
391 warnif_rule_after_use_backend(proxy, file, line, arg);
392}
393
394/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_redirect(proxy, file, line, arg) ||
406 warnif_rule_after_use_backend(proxy, file, line, arg);
407}
408
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100409/* Report it if a request ACL condition uses some response-only parameters. It
410 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
411 * Note that <cond> may be NULL and then will be ignored.
412 */
413static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
414{
415 struct acl *acl;
416
417 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
418 return 0;
419
420 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
421 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
422 file, line, acl ? acl->name : "(unknown)");
423 return ERR_WARN;
424}
425
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100426/* Report it if a request ACL condition uses some request-only volatile parameters.
427 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
428 * Note that <cond> may be NULL and then will be ignored.
429 */
430static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
431{
432 struct acl *acl;
433
434 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
435 return 0;
436
437 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
438 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
439 file, line, acl ? acl->name : "(unknown)");
440 return ERR_WARN;
441}
442
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100443
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200445 * parse a line in a <global> section. Returns the error code, 0 if OK, or
446 * any combination of :
447 * - ERR_ABORT: must abort ASAP
448 * - ERR_FATAL: we can continue parsing but not start the service
449 * - ERR_WARN: a warning has been emitted
450 * - ERR_ALERT: an alert has been emitted
451 * Only the two first ones can stop processing, the two others are just
452 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200454int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455{
Willy Tarreau058e9072009-07-20 09:30:05 +0200456 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200457
458 if (!strcmp(args[0], "global")) { /* new section */
459 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 }
462 else if (!strcmp(args[0], "daemon")) {
463 global.mode |= MODE_DAEMON;
464 }
465 else if (!strcmp(args[0], "debug")) {
466 global.mode |= MODE_DEBUG;
467 }
468 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100469 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100472 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200473 }
474 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100475 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100480 else if (!strcmp(args[0], "nosplice")) {
481 global.tune.options &= ~GTUNE_USE_SPLICE;
482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483 else if (!strcmp(args[0], "quiet")) {
484 global.mode |= MODE_QUIET;
485 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200486 else if (!strcmp(args[0], "tune.maxpollevents")) {
487 if (global.tune.maxpollevents != 0) {
488 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200489 err_code |= ERR_ALERT;
490 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200491 }
492 if (*(args[1]) == 0) {
493 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200494 err_code |= ERR_ALERT | ERR_FATAL;
495 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200496 }
497 global.tune.maxpollevents = atol(args[1]);
498 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100499 else if (!strcmp(args[0], "tune.maxaccept")) {
500 if (global.tune.maxaccept != 0) {
501 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200502 err_code |= ERR_ALERT;
503 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100504 }
505 if (*(args[1]) == 0) {
506 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200507 err_code |= ERR_ALERT | ERR_FATAL;
508 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100509 }
510 global.tune.maxaccept = atol(args[1]);
511 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200512 else if (!strcmp(args[0], "tune.chksize")) {
513 if (*(args[1]) == 0) {
514 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
517 }
518 global.tune.chksize = atol(args[1]);
519 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200520 else if (!strcmp(args[0], "tune.bufsize")) {
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.bufsize = atol(args[1]);
527 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
528 global.tune.maxrewrite = global.tune.bufsize / 2;
529 }
530 else if (!strcmp(args[0], "tune.maxrewrite")) {
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
535 }
536 global.tune.maxrewrite = atol(args[1]);
537 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
538 global.tune.maxrewrite = global.tune.bufsize / 2;
539 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100540 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
541 if (global.tune.client_rcvbuf != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
543 err_code |= ERR_ALERT;
544 goto out;
545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
550 }
551 global.tune.client_rcvbuf = atol(args[1]);
552 }
553 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
554 if (global.tune.server_rcvbuf != 0) {
555 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT;
557 goto out;
558 }
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.tune.server_rcvbuf = atol(args[1]);
565 }
566 else if (!strcmp(args[0], "tune.sndbuf.client")) {
567 if (global.tune.client_sndbuf != 0) {
568 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT;
570 goto out;
571 }
572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
576 }
577 global.tune.client_sndbuf = atol(args[1]);
578 }
579 else if (!strcmp(args[0], "tune.sndbuf.server")) {
580 if (global.tune.server_sndbuf != 0) {
581 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT;
583 goto out;
584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.server_sndbuf = atol(args[1]);
591 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200592 else if (!strcmp(args[0], "tune.pipesize")) {
593 if (*(args[1]) == 0) {
594 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT | ERR_FATAL;
596 goto out;
597 }
598 global.tune.pipesize = atol(args[1]);
599 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200600 else if (!strcmp(args[0], "tune.http.maxhdr")) {
601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.tune.max_http_hdr = atol(args[1]);
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "uid")) {
609 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200610 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 }
619 global.uid = atol(args[1]);
620 }
621 else if (!strcmp(args[0], "gid")) {
622 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200624 err_code |= ERR_ALERT;
625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 }
627 if (*(args[1]) == 0) {
628 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 }
632 global.gid = atol(args[1]);
633 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200634 /* user/group name handling */
635 else if (!strcmp(args[0], "user")) {
636 struct passwd *ha_user;
637 if (global.uid != 0) {
638 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT;
640 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200641 }
642 errno = 0;
643 ha_user = getpwnam(args[1]);
644 if (ha_user != NULL) {
645 global.uid = (int)ha_user->pw_uid;
646 }
647 else {
648 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 +0200649 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200650 }
651 }
652 else if (!strcmp(args[0], "group")) {
653 struct group *ha_group;
654 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200655 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200656 err_code |= ERR_ALERT;
657 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200658 }
659 errno = 0;
660 ha_group = getgrnam(args[1]);
661 if (ha_group != NULL) {
662 global.gid = (int)ha_group->gr_gid;
663 }
664 else {
665 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 +0200666 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200667 }
668 }
669 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 else if (!strcmp(args[0], "nbproc")) {
671 if (global.nbproc != 0) {
672 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 global.nbproc = atol(args[1]);
682 }
683 else if (!strcmp(args[0], "maxconn")) {
684 if (global.maxconn != 0) {
685 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT;
687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 }
689 if (*(args[1]) == 0) {
690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 global.maxconn = atol(args[1]);
695#ifdef SYSTEM_MAXCONN
696 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
697 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);
698 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 }
701#endif /* SYSTEM_MAXCONN */
702 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200703 else if (!strcmp(args[0], "maxconnrate")) {
704 if (global.cps_lim != 0) {
705 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
706 err_code |= ERR_ALERT;
707 goto out;
708 }
709 if (*(args[1]) == 0) {
710 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
711 err_code |= ERR_ALERT | ERR_FATAL;
712 goto out;
713 }
714 global.cps_lim = atol(args[1]);
715 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100716 else if (!strcmp(args[0], "maxpipes")) {
717 if (global.maxpipes != 0) {
718 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT;
720 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100721 }
722 if (*(args[1]) == 0) {
723 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200724 err_code |= ERR_ALERT | ERR_FATAL;
725 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100726 }
727 global.maxpipes = atol(args[1]);
728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 else if (!strcmp(args[0], "ulimit-n")) {
730 if (global.rlimit_nofile != 0) {
731 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200732 err_code |= ERR_ALERT;
733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 }
735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 }
740 global.rlimit_nofile = atol(args[1]);
741 }
742 else if (!strcmp(args[0], "chroot")) {
743 if (global.chroot != NULL) {
744 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT;
746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 }
748 if (*(args[1]) == 0) {
749 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 }
753 global.chroot = strdup(args[1]);
754 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200755 else if (!strcmp(args[0], "description")) {
756 int i, len=0;
757 char *d;
758
759 if (!*args[1]) {
760 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
761 file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 for(i=1; *args[i]; i++)
767 len += strlen(args[i])+1;
768
769 if (global.desc)
770 free(global.desc);
771
772 global.desc = d = (char *)calloc(1, len);
773
774 d += sprintf(d, "%s", args[1]);
775 for(i=2; *args[i]; i++)
776 d += sprintf(d, " %s", args[i]);
777 }
778 else if (!strcmp(args[0], "node")) {
779 int i;
780 char c;
781
782 for (i=0; args[1][i]; i++) {
783 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100784 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
785 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200786 break;
787 }
788
789 if (!i || args[1][i]) {
790 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
791 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
792 file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796
797 if (global.node)
798 free(global.node);
799
800 global.node = strdup(args[1]);
801 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802 else if (!strcmp(args[0], "pidfile")) {
803 if (global.pidfile != NULL) {
804 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT;
806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 }
808 if (*(args[1]) == 0) {
809 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 }
813 global.pidfile = strdup(args[1]);
814 }
Emeric Bruned760922010-10-22 17:59:25 +0200815 else if (!strcmp(args[0], "unix-bind")) {
816 int cur_arg = 1;
817 while (*(args[cur_arg])) {
818 if (!strcmp(args[cur_arg], "prefix")) {
819 if (global.unix_bind.prefix != NULL) {
820 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
821 err_code |= ERR_ALERT;
822 cur_arg += 2;
823 continue;
824 }
825
826 if (*(args[cur_arg+1]) == 0) {
827 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 global.unix_bind.prefix = strdup(args[cur_arg+1]);
832 cur_arg += 2;
833 continue;
834 }
835
836 if (!strcmp(args[cur_arg], "mode")) {
837
838 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
839 cur_arg += 2;
840 continue;
841 }
842
843 if (!strcmp(args[cur_arg], "uid")) {
844
845 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
846 cur_arg += 2;
847 continue;
848 }
849
850 if (!strcmp(args[cur_arg], "gid")) {
851
852 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
853 cur_arg += 2;
854 continue;
855 }
856
857 if (!strcmp(args[cur_arg], "user")) {
858 struct passwd *user;
859
860 user = getpwnam(args[cur_arg + 1]);
861 if (!user) {
862 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
863 file, linenum, args[0], args[cur_arg + 1 ]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867
868 global.unix_bind.ux.uid = user->pw_uid;
869 cur_arg += 2;
870 continue;
871 }
872
873 if (!strcmp(args[cur_arg], "group")) {
874 struct group *group;
875
876 group = getgrnam(args[cur_arg + 1]);
877 if (!group) {
878 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
879 file, linenum, args[0], args[cur_arg + 1 ]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883
884 global.unix_bind.ux.gid = group->gr_gid;
885 cur_arg += 2;
886 continue;
887 }
888
Willy Tarreaub48f9582011-09-05 01:17:06 +0200889 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200890 file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 }
William Lallemand0f99e342011-10-12 17:50:54 +0200895 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
896 /* delete previous herited or defined syslog servers */
897 struct logsrv *back;
898 struct logsrv *tmp;
899
900 if (*(args[1]) != 0) {
901 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
904 }
905
906 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
907 LIST_DEL(&tmp->list);
908 free(tmp);
909 }
910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200912 struct logsrv *logsrv;
913
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 if (*(args[1]) == 0 || *(args[2]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 }
William Lallemand0f99e342011-10-12 17:50:54 +0200919
920 logsrv = calloc(1, sizeof(struct logsrv));
921
922 logsrv->facility = get_log_facility(args[2]);
923 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200926 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928
William Lallemand0f99e342011-10-12 17:50:54 +0200929 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200931 logsrv->level = get_log_level(args[3]);
932 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200934 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200935 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 }
937 }
938
William Lallemand0f99e342011-10-12 17:50:54 +0200939 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200940 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200941 logsrv->minlvl = get_log_level(args[4]);
942 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200943 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200944 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200945 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200946 }
947 }
948
Robert Tsai81ae1952007-12-05 10:47:29 +0100949 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100950 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100951 if (!sk) {
952 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100953 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100954 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200955 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100956 goto out;
957 }
William Lallemand0f99e342011-10-12 17:50:54 +0200958 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100960 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100961 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100962 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
963 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200964 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100965 goto out;
966 }
William Lallemand0f99e342011-10-12 17:50:54 +0200967 logsrv->addr = *sk;
968 if (!get_host_port(&logsrv->addr))
969 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971
William Lallemand0f99e342011-10-12 17:50:54 +0200972 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200973 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100974 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
975 char *name;
976 int len;
977
978 if (global.log_send_hostname != NULL) {
979 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
980 err_code |= ERR_ALERT;
981 goto out;
982 }
983
984 if (*(args[1]))
985 name = args[1];
986 else
987 name = hostname;
988
989 len = strlen(name);
990
991 /* We'll add a space after the name to respect the log format */
992 free(global.log_send_hostname);
993 global.log_send_hostname = malloc(len + 2);
994 snprintf(global.log_send_hostname, len + 2, "%s ", name);
995 }
Kevinm48936af2010-12-22 16:08:21 +0000996 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 free(global.log_tag);
1003 global.log_tag = strdup(args[1]);
1004 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001005 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1006 if (global.spread_checks != 0) {
1007 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001008 err_code |= ERR_ALERT;
1009 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
1011 if (*(args[1]) == 0) {
1012 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 }
1016 global.spread_checks = atol(args[1]);
1017 if (global.spread_checks < 0 || global.spread_checks > 50) {
1018 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 }
1022 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001023 struct cfg_kw_list *kwl;
1024 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001025 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001026
1027 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1028 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1029 if (kwl->kw[index].section != CFG_GLOBAL)
1030 continue;
1031 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1032 /* prepare error message just in case */
1033 snprintf(trash, sizeof(trash),
1034 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001035 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1036 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001037 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001038 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001039 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001040 else if (rc > 0) {
1041 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_WARN;
1043 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001044 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001046 }
1047 }
1048 }
1049
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001051 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001053
Willy Tarreau058e9072009-07-20 09:30:05 +02001054 out:
1055 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056}
1057
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001058void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001060 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061 defproxy.mode = PR_MODE_TCP;
1062 defproxy.state = PR_STNEW;
1063 defproxy.maxconn = cfg_maxpconn;
1064 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001065
1066 defproxy.defsrv.inter = DEF_CHKINTR;
1067 defproxy.defsrv.fastinter = 0;
1068 defproxy.defsrv.downinter = 0;
1069 defproxy.defsrv.rise = DEF_RISETIME;
1070 defproxy.defsrv.fall = DEF_FALLTIME;
1071 defproxy.defsrv.check_port = 0;
1072 defproxy.defsrv.maxqueue = 0;
1073 defproxy.defsrv.minconn = 0;
1074 defproxy.defsrv.maxconn = 0;
1075 defproxy.defsrv.slowstart = 0;
1076 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1077 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1078 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079}
1080
Willy Tarreauade5ec42010-01-28 19:33:49 +01001081
1082static int create_cond_regex_rule(const char *file, int line,
1083 struct proxy *px, int dir, int action, int flags,
1084 const char *cmd, const char *reg, const char *repl,
1085 const char **cond_start)
1086{
1087 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001088 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001089 const char *err;
1090 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001091 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001092
1093 if (px == &defproxy) {
1094 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto err;
1097 }
1098
1099 if (*reg == 0) {
1100 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto err;
1103 }
1104
1105 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1106 err_code |= ERR_WARN;
1107
Willy Tarreau5321c422010-01-28 20:35:13 +01001108 if (cond_start &&
1109 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001110 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1111 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1112 file, line, cmd, errmsg);
1113 free(errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto err;
1116 }
1117 }
1118 else if (cond_start && **cond_start) {
1119 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1120 file, line, cmd, *cond_start);
1121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto err;
1123 }
1124
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001125 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001126 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001127 else
1128 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001129
Willy Tarreauade5ec42010-01-28 19:33:49 +01001130 preg = calloc(1, sizeof(regex_t));
1131 if (!preg) {
1132 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1133 err_code = ERR_ALERT | ERR_FATAL;
1134 goto err;
1135 }
1136
1137 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1138 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1139 err_code = ERR_ALERT | ERR_FATAL;
1140 goto err;
1141 }
1142
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001143 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001144 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001145 if (repl && err) {
1146 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1147 file, line, cmd, *err);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto err;
1150 }
1151
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001152 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001153 err_code |= ERR_WARN;
1154
1155 return err_code;
1156 err:
1157 free(preg);
1158 return err_code;
1159}
1160
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001162 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001163 * Returns the error code, 0 if OK, or any combination of :
1164 * - ERR_ABORT: must abort ASAP
1165 * - ERR_FATAL: we can continue parsing but not start the service
1166 * - ERR_WARN: a warning has been emitted
1167 * - ERR_ALERT: an alert has been emitted
1168 * Only the two first ones can stop processing, the two others are just
1169 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001170 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001171int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1172{
1173 static struct peers *curpeers = NULL;
1174 struct peer *newpeer = NULL;
1175 const char *err;
1176 int err_code = 0;
1177
1178 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1179
1180 err = invalid_char(args[1]);
1181 if (err) {
1182 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1183 file, linenum, *err, args[0], args[1]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 }
1186
1187 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1188 /*
1189 * If there are two proxies with the same name only following
1190 * combinations are allowed:
1191 */
1192 if (strcmp(curpeers->id, args[1]) == 0) {
1193 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1194 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1195 err_code |= ERR_WARN;
1196 }
1197 }
1198
1199 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1200 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1201 err_code |= ERR_ALERT | ERR_ABORT;
1202 goto out;
1203 }
1204
1205 curpeers->next = peers;
1206 peers = curpeers;
1207 curpeers->conf.file = file;
1208 curpeers->conf.line = linenum;
1209 curpeers->last_change = now.tv_sec;
1210 curpeers->id = strdup(args[1]);
1211 }
1212 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1213 char *rport, *raddr;
1214 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001215 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001216
1217 if (!*args[2]) {
1218 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1219 file, linenum, args[0]);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
1222 }
1223
1224 err = invalid_char(args[1]);
1225 if (err) {
1226 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1227 file, linenum, *err, args[1]);
1228 err_code |= ERR_ALERT | ERR_FATAL;
1229 goto out;
1230 }
1231
1232 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1233 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1234 err_code |= ERR_ALERT | ERR_ABORT;
1235 goto out;
1236 }
1237
1238 /* the peers are linked backwards first */
1239 curpeers->count++;
1240 newpeer->next = curpeers->remote;
1241 curpeers->remote = newpeer;
1242 newpeer->peers = curpeers;
1243 newpeer->conf.file = file;
1244 newpeer->conf.line = linenum;
1245
1246 newpeer->last_change = now.tv_sec;
1247 newpeer->id = strdup(args[1]);
1248
1249 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001250 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001251 if (rport) {
1252 *rport++ = 0;
1253 realport = atol(rport);
1254 }
1255 if (!realport) {
1256 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
1259 }
1260
Willy Tarreaufab5a432011-03-04 15:31:53 +01001261 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001262 free(raddr);
1263 if (!sk) {
1264 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
1267 }
1268 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001269 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
1270
1271 if (!sk) {
1272 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1273 file, linenum, newpeer->addr.ss_family, args[2]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001278 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001279
1280 if (strcmp(newpeer->id, localpeer) == 0) {
1281 /* Current is local peer, it define a frontend */
1282 newpeer->local = 1;
1283
1284 if (!curpeers->peers_fe) {
1285 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1286 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1287 err_code |= ERR_ALERT | ERR_ABORT;
1288 goto out;
1289 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001290
Willy Tarreau237250c2011-07-29 01:49:03 +02001291 init_new_proxy(curpeers->peers_fe);
1292 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001293
1294 curpeers->peers_fe->last_change = now.tv_sec;
1295 curpeers->peers_fe->id = strdup(args[1]);
1296 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001297 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001298 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1299 curpeers->peers_fe->timeout.connect = 5000;
1300 curpeers->peers_fe->accept = peer_accept;
1301 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001302 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001303 err_code |= ERR_FATAL;
1304 goto out;
1305 }
1306 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1307 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1308 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1309 curpeers->peers_fe->listen->accept = session_accept;
1310 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1311 curpeers->peers_fe->listen->handler = process_session;
1312 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001313 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1314 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001315 }
1316 }
1317 } /* neither "peer" nor "peers" */
1318 else if (*args[0] != 0) {
1319 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1320 err_code |= ERR_ALERT | ERR_FATAL;
1321 goto out;
1322 }
1323
1324out:
1325 return err_code;
1326}
1327
1328
Willy Tarreau3842f002009-06-14 11:39:52 +02001329int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001330{
1331 static struct proxy *curproxy = NULL;
1332 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001333 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001334 int rc;
1335 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001336 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001337 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001338 struct logsrv *tmplogsrv;
1339 struct logformat_node *tmplf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340
Willy Tarreau977b8e42006-12-29 14:19:17 +01001341 if (!strcmp(args[0], "listen"))
1342 rc = PR_CAP_LISTEN;
1343 else if (!strcmp(args[0], "frontend"))
1344 rc = PR_CAP_FE | PR_CAP_RS;
1345 else if (!strcmp(args[0], "backend"))
1346 rc = PR_CAP_BE | PR_CAP_RS;
1347 else if (!strcmp(args[0], "ruleset"))
1348 rc = PR_CAP_RS;
1349 else
1350 rc = PR_CAP_NONE;
1351
1352 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 if (!*args[1]) {
1354 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1355 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1356 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001357 err_code |= ERR_ALERT | ERR_ABORT;
1358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001359 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001360
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001361 err = invalid_char(args[1]);
1362 if (err) {
1363 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1364 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001365 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001366 }
1367
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001368 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1369 /*
1370 * If there are two proxies with the same name only following
1371 * combinations are allowed:
1372 *
1373 * listen backend frontend ruleset
1374 * listen - - - -
1375 * backend - - OK -
1376 * frontend - OK - -
1377 * ruleset - - - -
1378 */
1379
1380 if (!strcmp(curproxy->id, args[1]) &&
1381 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1382 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001383 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1384 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1385 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001386 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001387 }
1388 }
1389
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1391 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001392 err_code |= ERR_ALERT | ERR_ABORT;
1393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001395
Willy Tarreau97cb7802010-01-03 20:23:58 +01001396 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001397 curproxy->next = proxy;
1398 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001399 curproxy->conf.file = file;
1400 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001401 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001403 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404
1405 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001406 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001407 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001408 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001409 err_code |= ERR_FATAL;
1410 goto out;
1411 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001412 new = curproxy->listen;
1413 while (new != last) {
1414 new->conf.file = file;
1415 new->conf.line = linenum;
1416 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001417 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 }
1420
1421 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001422 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001423 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001424
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001427 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001428 curproxy->no_options = defproxy.no_options;
1429 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001430 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001431 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001432 curproxy->except_net = defproxy.except_net;
1433 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001434 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001435 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001437 if (defproxy.fwdfor_hdr_len) {
1438 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1439 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1440 }
1441
Willy Tarreaub86db342009-11-30 11:50:16 +01001442 if (defproxy.orgto_hdr_len) {
1443 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1444 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1445 }
1446
Mark Lamourinec2247f02012-01-04 13:02:01 -05001447 if (defproxy.server_id_hdr_len) {
1448 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1449 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1450 }
1451
Willy Tarreau977b8e42006-12-29 14:19:17 +01001452 if (curproxy->cap & PR_CAP_FE) {
1453 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001454 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001455 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001456
1457 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001458 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1459 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001460
1461 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1462 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 if (curproxy->cap & PR_CAP_BE) {
1465 curproxy->fullconn = defproxy.fullconn;
1466 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001468 if (defproxy.check_req) {
1469 curproxy->check_req = calloc(1, defproxy.check_len);
1470 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1471 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001474 if (defproxy.expect_str) {
1475 curproxy->expect_str = strdup(defproxy.expect_str);
1476 if (defproxy.expect_regex) {
1477 /* note: this regex is known to be valid */
1478 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1479 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1480 }
1481 }
1482
Willy Tarreau977b8e42006-12-29 14:19:17 +01001483 if (defproxy.cookie_name)
1484 curproxy->cookie_name = strdup(defproxy.cookie_name);
1485 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001486 if (defproxy.cookie_domain)
1487 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001488
Willy Tarreau31936852010-10-06 16:59:56 +02001489 if (defproxy.cookie_maxidle)
1490 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1491
1492 if (defproxy.cookie_maxlife)
1493 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1494
Emeric Brun647caf12009-06-30 17:57:00 +02001495 if (defproxy.rdp_cookie_name)
1496 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1497 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1498
Willy Tarreau01732802007-11-01 22:48:15 +01001499 if (defproxy.url_param_name)
1500 curproxy->url_param_name = strdup(defproxy.url_param_name);
1501 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001502
Benoitaffb4812009-03-25 13:02:10 +01001503 if (defproxy.hh_name)
1504 curproxy->hh_name = strdup(defproxy.hh_name);
1505 curproxy->hh_len = defproxy.hh_len;
1506 curproxy->hh_match_domain = defproxy.hh_match_domain;
1507
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001508 if (defproxy.iface_name)
1509 curproxy->iface_name = strdup(defproxy.iface_name);
1510 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001512
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001513 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 if (defproxy.capture_name)
1515 curproxy->capture_name = strdup(defproxy.capture_name);
1516 curproxy->capture_namelen = defproxy.capture_namelen;
1517 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519
Willy Tarreau977b8e42006-12-29 14:19:17 +01001520 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001521 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001522 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001523 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001524 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001525 curproxy->uri_auth = defproxy.uri_auth;
1526 curproxy->mon_net = defproxy.mon_net;
1527 curproxy->mon_mask = defproxy.mon_mask;
1528 if (defproxy.monitor_uri)
1529 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1530 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001531 if (defproxy.defbe.name)
1532 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001533 }
1534
1535 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001536 curproxy->timeout.connect = defproxy.timeout.connect;
1537 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001538 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001539 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001540 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001541 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001542 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001543 curproxy->source_addr = defproxy.source_addr;
1544 }
1545
Willy Tarreaubaaee002006-06-26 02:48:02 +02001546 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001547
1548 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001549 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001550 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001551 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001552 LIST_INIT(&node->list);
1553 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1554 }
1555
William Lallemand723b73a2012-02-08 16:37:49 +01001556 /* copy default log_format to curproxy */
1557 list_for_each_entry(tmplf, &defproxy.logformat, list) {
1558 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1559 memcpy(node, tmplf, sizeof(struct logformat_node));
1560 LIST_INIT(&node->list);
1561 LIST_ADDQ(&curproxy->logformat, &node->list);
1562 }
1563
William Lallemanda73203e2012-03-12 12:48:57 +01001564 /* copy default unique_id to curproxy */
1565 list_for_each_entry(tmplf, &defproxy.format_unique_id, list) {
1566 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1567 memcpy(node, tmplf, sizeof(struct logformat_node));
1568 LIST_INIT(&node->list);
1569 LIST_ADDQ(&curproxy->format_unique_id, &node->list);
1570 }
1571
1572 /* copy default header unique id */
1573 if (defproxy.header_unique_id)
1574 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1575
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001577 curproxy->conf.used_listener_id = EB_ROOT;
1578 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001579
Willy Tarreau93893792009-07-23 13:19:11 +02001580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 }
1582 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1583 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001584 /* FIXME-20070101: we should do this too at the end of the
1585 * config parsing to free all default values.
1586 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001587 free(defproxy.check_req);
1588 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001589 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001590 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001591 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001592 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001593 free(defproxy.capture_name);
1594 free(defproxy.monitor_uri);
1595 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001596 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001597 free(defproxy.fwdfor_hdr_name);
1598 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001599 free(defproxy.orgto_hdr_name);
1600 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001601 free(defproxy.server_id_hdr_name);
1602 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001603 free(defproxy.expect_str);
1604 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001605
Willy Tarreaua534fea2008-08-03 12:19:50 +02001606 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001607 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001608
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 /* we cannot free uri_auth because it might already be used */
1610 init_default_instance();
1611 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001612 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 }
1615 else if (curproxy == NULL) {
1616 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001617 err_code |= ERR_ALERT | ERR_FATAL;
1618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001619 }
1620
Willy Tarreau977b8e42006-12-29 14:19:17 +01001621
1622 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001624 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001625 int cur_arg;
1626
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 if (curproxy == &defproxy) {
1628 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001629 err_code |= ERR_ALERT | ERR_FATAL;
1630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001632 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001633 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634
Emeric Bruned760922010-10-22 17:59:25 +02001635 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001636 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001637 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001641
1642 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001643
1644 /* NOTE: the following line might create several listeners if there
1645 * are comma-separated IPs or port ranges. So all further processing
1646 * will have to be applied to all listeners created after last_listen.
1647 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001648 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001649 err_code |= ERR_ALERT | ERR_FATAL;
1650 goto out;
1651 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001652
Willy Tarreau90a570f2009-10-04 20:54:54 +02001653 new_listen = curproxy->listen;
1654 while (new_listen != last_listen) {
1655 new_listen->conf.file = file;
1656 new_listen->conf.line = linenum;
1657 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001658 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001659 }
1660
Emeric Bruned760922010-10-22 17:59:25 +02001661 /* Set default global rights and owner for unix bind */
1662 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1663 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1664 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001665 cur_arg = 2;
1666 while (*(args[cur_arg])) {
1667 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1668#ifdef SO_BINDTODEVICE
1669 struct listener *l;
1670
Emeric Bruned760922010-10-22 17:59:25 +02001671 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1672 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1673 file, linenum, args[0], args[cur_arg]);
1674 err_code |= ERR_ALERT | ERR_FATAL;
1675 goto out;
1676 }
1677
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001678 if (!*args[cur_arg + 1]) {
1679 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1680 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001681 err_code |= ERR_ALERT | ERR_FATAL;
1682 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001683 }
1684
1685 for (l = curproxy->listen; l != last_listen; l = l->next)
1686 l->interface = strdup(args[cur_arg + 1]);
1687
1688 global.last_checks |= LSTCHK_NETADM;
1689
1690 cur_arg += 2;
1691 continue;
1692#else
1693 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1694 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001697#endif
1698 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001699 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1700#ifdef TCP_MAXSEG
1701 struct listener *l;
1702 int mss;
1703
Emeric Bruned760922010-10-22 17:59:25 +02001704 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1705 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1706 file, linenum, args[0], args[cur_arg]);
1707 err_code |= ERR_ALERT | ERR_FATAL;
1708 goto out;
1709 }
1710
Willy Tarreaube1b9182009-06-14 18:48:19 +02001711 if (!*args[cur_arg + 1]) {
1712 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1713 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001714 err_code |= ERR_ALERT | ERR_FATAL;
1715 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001716 }
1717
Willy Tarreau48a7e722010-12-24 15:26:39 +01001718 mss = atoi(args[cur_arg + 1]);
1719 if (!mss || abs(mss) > 65535) {
1720 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001721 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001722 err_code |= ERR_ALERT | ERR_FATAL;
1723 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001724 }
1725
1726 for (l = curproxy->listen; l != last_listen; l = l->next)
1727 l->maxseg = mss;
1728
1729 cur_arg += 2;
1730 continue;
1731#else
1732 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1733 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001734 err_code |= ERR_ALERT | ERR_FATAL;
1735 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001736#endif
1737 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001738
1739 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1740#ifdef TCP_DEFER_ACCEPT
1741 struct listener *l;
1742
1743 for (l = curproxy->listen; l != last_listen; l = l->next)
1744 l->options |= LI_O_DEF_ACCEPT;
1745
1746 cur_arg ++;
1747 continue;
1748#else
1749 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1750 file, linenum, args[0], args[cur_arg]);
1751 err_code |= ERR_ALERT | ERR_FATAL;
1752 goto out;
1753#endif
1754 }
1755
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001756 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001757#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001758 struct listener *l;
1759
Emeric Bruned760922010-10-22 17:59:25 +02001760 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1761 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1762 file, linenum, args[0], args[cur_arg]);
1763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
1765 }
1766
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001767 for (l = curproxy->listen; l != last_listen; l = l->next)
1768 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001769
1770 cur_arg ++;
1771 continue;
1772#else
1773 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1774 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001775 err_code |= ERR_ALERT | ERR_FATAL;
1776 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001777#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001778 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001779
Willy Tarreau8a956912010-10-15 14:27:08 +02001780 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1781 struct listener *l;
1782
1783 for (l = curproxy->listen; l != last_listen; l = l->next)
1784 l->options |= LI_O_ACC_PROXY;
1785
1786 cur_arg ++;
1787 continue;
1788 }
1789
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001790 if (!strcmp(args[cur_arg], "name")) {
1791 struct listener *l;
1792
1793 for (l = curproxy->listen; l != last_listen; l = l->next)
1794 l->name = strdup(args[cur_arg + 1]);
1795
1796 cur_arg += 2;
1797 continue;
1798 }
1799
1800 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001801 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001802 struct listener *l;
1803
1804 if (curproxy->listen->next != last_listen) {
1805 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1806 file, linenum, args[cur_arg]);
1807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
1809 }
1810
1811 if (!*args[cur_arg + 1]) {
1812 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1813 file, linenum, args[cur_arg]);
1814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
1816 }
1817
1818 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001819 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001820
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001821 if (curproxy->listen->luid <= 0) {
1822 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001823 file, linenum);
1824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001828 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1829 if (node) {
1830 l = container_of(node, struct listener, conf.id);
1831 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1832 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
1835 }
1836 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1837
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001838 cur_arg += 2;
1839 continue;
1840 }
1841
Emeric Bruned760922010-10-22 17:59:25 +02001842 if (!strcmp(args[cur_arg], "mode")) {
1843
1844 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1845 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1846 file, linenum, args[0], args[cur_arg]);
1847 err_code |= ERR_ALERT | ERR_FATAL;
1848 goto out;
1849 }
1850
1851 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1852
1853 cur_arg += 2;
1854 continue;
1855 }
1856
1857 if (!strcmp(args[cur_arg], "uid")) {
1858
1859 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1860 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1861 file, linenum, args[0], args[cur_arg]);
1862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
1864 }
1865
1866 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1867 cur_arg += 2;
1868 continue;
1869 }
1870
1871 if (!strcmp(args[cur_arg], "gid")) {
1872
1873 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1874 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1875 file, linenum, args[0], args[cur_arg]);
1876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
1878 }
1879
1880 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1881 cur_arg += 2;
1882 continue;
1883 }
1884
1885 if (!strcmp(args[cur_arg], "user")) {
1886 struct passwd *user;
1887
1888 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1889 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1890 file, linenum, args[0], args[cur_arg]);
1891 err_code |= ERR_ALERT | ERR_FATAL;
1892 goto out;
1893 }
1894 user = getpwnam(args[cur_arg + 1]);
1895 if (!user) {
1896 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1897 file, linenum, args[0], args[cur_arg + 1 ]);
1898 err_code |= ERR_ALERT | ERR_FATAL;
1899 goto out;
1900 }
1901
1902 curproxy->listen->perm.ux.uid = user->pw_uid;
1903 cur_arg += 2;
1904 continue;
1905 }
1906
1907 if (!strcmp(args[cur_arg], "group")) {
1908 struct group *group;
1909
1910 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1911 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1912 file, linenum, args[0], args[cur_arg]);
1913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
1915 }
1916 group = getgrnam(args[cur_arg + 1]);
1917 if (!group) {
1918 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1919 file, linenum, args[0], args[cur_arg + 1 ]);
1920 err_code |= ERR_ALERT | ERR_FATAL;
1921 goto out;
1922 }
1923
1924 curproxy->listen->perm.ux.gid = group->gr_gid;
1925 cur_arg += 2;
1926 continue;
1927 }
1928
Willy Tarreaub48f9582011-09-05 01:17:06 +02001929 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss', 'mode', 'uid', 'gid', 'user', 'group' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001933 }
Willy Tarreau93893792009-07-23 13:19:11 +02001934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 }
1936 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1937 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1938 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001940 err_code |= ERR_ALERT | ERR_FATAL;
1941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001943 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001944 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001945
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 /* flush useless bits */
1947 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001950 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001951 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001952 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001953
Willy Tarreau1c47f852006-07-09 08:22:27 +02001954 if (!*args[1]) {
1955 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1956 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001957 err_code |= ERR_ALERT | ERR_FATAL;
1958 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001959 }
1960
Willy Tarreaua534fea2008-08-03 12:19:50 +02001961 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001962 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001963 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001964 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001965 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1966
Willy Tarreau93893792009-07-23 13:19:11 +02001967 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1970 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1971 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1972 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1973 else {
1974 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 }
1978 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001979 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001980 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001981
1982 if (curproxy == &defproxy) {
1983 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1984 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001985 err_code |= ERR_ALERT | ERR_FATAL;
1986 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001987 }
1988
1989 if (!*args[1]) {
1990 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1991 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001992 err_code |= ERR_ALERT | ERR_FATAL;
1993 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001994 }
1995
1996 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001997 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001998
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001999 if (curproxy->uuid <= 0) {
2000 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002001 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002004 }
2005
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002006 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2007 if (node) {
2008 struct proxy *target = container_of(node, struct proxy, conf.id);
2009 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2010 file, linenum, proxy_type_str(curproxy), curproxy->id,
2011 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2012 err_code |= ERR_ALERT | ERR_FATAL;
2013 goto out;
2014 }
2015 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002016 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002017 else if (!strcmp(args[0], "description")) {
2018 int i, len=0;
2019 char *d;
2020
Cyril Bonté99ed3272010-01-24 23:29:44 +01002021 if (curproxy == &defproxy) {
2022 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2023 file, linenum, args[0]);
2024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
2026 }
2027
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002028 if (!*args[1]) {
2029 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2030 file, linenum, args[0]);
2031 return -1;
2032 }
2033
2034 for(i=1; *args[i]; i++)
2035 len += strlen(args[i])+1;
2036
2037 d = (char *)calloc(1, len);
2038 curproxy->desc = d;
2039
2040 d += sprintf(d, "%s", args[1]);
2041 for(i=2; *args[i]; i++)
2042 d += sprintf(d, " %s", args[i]);
2043
2044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002045 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2046 curproxy->state = PR_STSTOPPED;
2047 }
2048 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2049 curproxy->state = PR_STNEW;
2050 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002051 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2052 int cur_arg = 1;
2053 unsigned int set = 0;
2054
2055 while (*args[cur_arg]) {
2056 int u;
2057 if (strcmp(args[cur_arg], "all") == 0) {
2058 set = 0;
2059 break;
2060 }
2061 else if (strcmp(args[cur_arg], "odd") == 0) {
2062 set |= 0x55555555;
2063 }
2064 else if (strcmp(args[cur_arg], "even") == 0) {
2065 set |= 0xAAAAAAAA;
2066 }
2067 else {
2068 u = str2uic(args[cur_arg]);
2069 if (u < 1 || u > 32) {
2070 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2071 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002074 }
2075 if (u > global.nbproc) {
2076 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2077 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002078 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002079 }
2080 set |= 1 << (u - 1);
2081 }
2082 cur_arg++;
2083 }
2084 curproxy->bind_proc = set;
2085 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002086 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002087 char *errmsg = NULL;
2088
Willy Tarreaub099aca2008-10-12 17:26:37 +02002089 if (curproxy == &defproxy) {
2090 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002091 err_code |= ERR_ALERT | ERR_FATAL;
2092 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002093 }
2094
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002095 err = invalid_char(args[1]);
2096 if (err) {
2097 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2098 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002099 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002100 }
2101
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002102 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2103 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2104 file, linenum, args[1], errmsg);
2105 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002106 err_code |= ERR_ALERT | ERR_FATAL;
2107 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002108 }
2109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2111 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112
Willy Tarreau977b8e42006-12-29 14:19:17 +01002113 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 if (*(args[1]) == 0) {
2117 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2118 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002119 err_code |= ERR_ALERT | ERR_FATAL;
2120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002122
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002123 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002124 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002125 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002126 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002127 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128 curproxy->cookie_name = strdup(args[1]);
2129 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002130
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 cur_arg = 2;
2132 while (*(args[cur_arg])) {
2133 if (!strcmp(args[cur_arg], "rewrite")) {
2134 curproxy->options |= PR_O_COOK_RW;
2135 }
2136 else if (!strcmp(args[cur_arg], "indirect")) {
2137 curproxy->options |= PR_O_COOK_IND;
2138 }
2139 else if (!strcmp(args[cur_arg], "insert")) {
2140 curproxy->options |= PR_O_COOK_INS;
2141 }
2142 else if (!strcmp(args[cur_arg], "nocache")) {
2143 curproxy->options |= PR_O_COOK_NOC;
2144 }
2145 else if (!strcmp(args[cur_arg], "postonly")) {
2146 curproxy->options |= PR_O_COOK_POST;
2147 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002148 else if (!strcmp(args[cur_arg], "preserve")) {
2149 curproxy->options2 |= PR_O2_COOK_PSV;
2150 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 else if (!strcmp(args[cur_arg], "prefix")) {
2152 curproxy->options |= PR_O_COOK_PFX;
2153 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002154 else if (!strcmp(args[cur_arg], "domain")) {
2155 if (!*args[cur_arg + 1]) {
2156 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2157 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002160 }
2161
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002162 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002163 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002164 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2165 " dots nor does not start with a dot."
2166 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002167 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002168 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002169 }
2170
2171 err = invalid_domainchar(args[cur_arg + 1]);
2172 if (err) {
2173 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2174 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002177 }
2178
Willy Tarreau68a897b2009-12-03 23:28:34 +01002179 if (!curproxy->cookie_domain) {
2180 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2181 } else {
2182 /* one domain was already specified, add another one by
2183 * building the string which will be returned along with
2184 * the cookie.
2185 */
2186 char *new_ptr;
2187 int new_len = strlen(curproxy->cookie_domain) +
2188 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2189 new_ptr = malloc(new_len);
2190 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2191 free(curproxy->cookie_domain);
2192 curproxy->cookie_domain = new_ptr;
2193 }
Willy Tarreau31936852010-10-06 16:59:56 +02002194 cur_arg++;
2195 }
2196 else if (!strcmp(args[cur_arg], "maxidle")) {
2197 unsigned int maxidle;
2198 const char *res;
2199
2200 if (!*args[cur_arg + 1]) {
2201 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2202 file, linenum, args[cur_arg]);
2203 err_code |= ERR_ALERT | ERR_FATAL;
2204 goto out;
2205 }
2206
2207 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2208 if (res) {
2209 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2210 file, linenum, *res, args[cur_arg]);
2211 err_code |= ERR_ALERT | ERR_FATAL;
2212 goto out;
2213 }
2214 curproxy->cookie_maxidle = maxidle;
2215 cur_arg++;
2216 }
2217 else if (!strcmp(args[cur_arg], "maxlife")) {
2218 unsigned int maxlife;
2219 const char *res;
2220
2221 if (!*args[cur_arg + 1]) {
2222 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2223 file, linenum, args[cur_arg]);
2224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
2226 }
2227
2228 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2229 if (res) {
2230 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2231 file, linenum, *res, args[cur_arg]);
2232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
2234 }
2235 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002236 cur_arg++;
2237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002239 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 +02002240 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 }
2244 cur_arg++;
2245 }
2246 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2247 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2248 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 }
2251
2252 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2253 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2254 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002255 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002257
2258 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2259 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2260 file, linenum);
2261 err_code |= ERR_ALERT | ERR_FATAL;
2262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002264 else if (!strcmp(args[0], "persist")) { /* persist */
2265 if (*(args[1]) == 0) {
2266 Alert("parsing [%s:%d] : missing persist method.\n",
2267 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002270 }
2271
2272 if (!strncmp(args[1], "rdp-cookie", 10)) {
2273 curproxy->options2 |= PR_O2_RDPC_PRST;
2274
Emeric Brunb982a3d2010-01-04 15:45:53 +01002275 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002276 const char *beg, *end;
2277
2278 beg = args[1] + 11;
2279 end = strchr(beg, ')');
2280
2281 if (!end || end == beg) {
2282 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2283 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002286 }
2287
2288 free(curproxy->rdp_cookie_name);
2289 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2290 curproxy->rdp_cookie_len = end-beg;
2291 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002292 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002293 free(curproxy->rdp_cookie_name);
2294 curproxy->rdp_cookie_name = strdup("msts");
2295 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2296 }
2297 else { /* syntax */
2298 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2299 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002302 }
2303 }
2304 else {
2305 Alert("parsing [%s:%d] : unknown persist method.\n",
2306 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002309 }
2310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002312 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002314 if (curproxy == &defproxy) {
2315 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
2318 }
2319
Willy Tarreau977b8e42006-12-29 14:19:17 +01002320 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002321 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002322
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002324 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002325 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 }
2329 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002330 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 curproxy->appsession_name = strdup(args[1]);
2332 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2333 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002334 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2335 if (err) {
2336 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2337 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002340 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002341 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002342
Willy Tarreau51041c72007-09-09 21:56:53 +02002343 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2344 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002345 err_code |= ERR_ALERT | ERR_ABORT;
2346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002348
2349 cur_arg = 6;
2350 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002351 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2352 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002353 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002354 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002355 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002356 } else if (!strcmp(args[cur_arg], "prefix")) {
2357 curproxy->options2 |= PR_O2_AS_PFX;
2358 } else if (!strcmp(args[cur_arg], "mode")) {
2359 if (!*args[cur_arg + 1]) {
2360 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2361 file, linenum, args[0], args[cur_arg]);
2362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
2365
2366 cur_arg++;
2367 if (!strcmp(args[cur_arg], "query-string")) {
2368 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2369 curproxy->options2 |= PR_O2_AS_M_QS;
2370 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2371 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2372 curproxy->options2 |= PR_O2_AS_M_PP;
2373 } else {
2374 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002379 cur_arg++;
2380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 } /* Url App Session */
2382 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002383 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002384 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002385
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002387 if (curproxy == &defproxy) {
2388 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2389 err_code |= ERR_ALERT | ERR_FATAL;
2390 goto out;
2391 }
2392
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 if (*(args[4]) == 0) {
2394 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2395 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002399 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 curproxy->capture_name = strdup(args[2]);
2401 curproxy->capture_namelen = strlen(curproxy->capture_name);
2402 curproxy->capture_len = atol(args[4]);
2403 if (curproxy->capture_len >= CAPTURE_LEN) {
2404 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2405 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002406 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 curproxy->capture_len = CAPTURE_LEN - 1;
2408 }
2409 curproxy->to_log |= LW_COOKIE;
2410 }
2411 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2412 struct cap_hdr *hdr;
2413
2414 if (curproxy == &defproxy) {
2415 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 +02002416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 }
2419
2420 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2421 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2422 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 }
2426
2427 hdr = calloc(sizeof(struct cap_hdr), 1);
2428 hdr->next = curproxy->req_cap;
2429 hdr->name = strdup(args[3]);
2430 hdr->namelen = strlen(args[3]);
2431 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002432 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 hdr->index = curproxy->nb_req_cap++;
2434 curproxy->req_cap = hdr;
2435 curproxy->to_log |= LW_REQHDR;
2436 }
2437 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2438 struct cap_hdr *hdr;
2439
2440 if (curproxy == &defproxy) {
2441 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 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 }
2445
2446 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2447 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2448 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
2452 hdr = calloc(sizeof(struct cap_hdr), 1);
2453 hdr->next = curproxy->rsp_cap;
2454 hdr->name = strdup(args[3]);
2455 hdr->namelen = strlen(args[3]);
2456 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002457 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 hdr->index = curproxy->nb_rsp_cap++;
2459 curproxy->rsp_cap = hdr;
2460 curproxy->to_log |= LW_RSPHDR;
2461 }
2462 else {
2463 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2464 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 }
2468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002470 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002472
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 if (*(args[1]) == 0) {
2474 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2475 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 }
2479 curproxy->conn_retries = atol(args[1]);
2480 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002481 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002482 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002483
2484 if (curproxy == &defproxy) {
2485 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
2488 }
2489
Willy Tarreauff011f22011-01-06 17:51:27 +01002490 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002491 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2492 file, linenum, args[0]);
2493 err_code |= ERR_WARN;
2494 }
2495
Willy Tarreauff011f22011-01-06 17:51:27 +01002496 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002497
Willy Tarreauff011f22011-01-06 17:51:27 +01002498 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002499 err_code |= ERR_ALERT | ERR_ABORT;
2500 goto out;
2501 }
2502
Willy Tarreauff011f22011-01-06 17:51:27 +01002503 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2504 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002505 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002506 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2507 /* set the header name and length into the proxy structure */
2508 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2509 err_code |= ERR_WARN;
2510
2511 if (!*args[1]) {
2512 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2513 file, linenum, args[0]);
2514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
2516 }
2517
2518 /* set the desired header name */
2519 free(curproxy->server_id_hdr_name);
2520 curproxy->server_id_hdr_name = strdup(args[1]);
2521 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2522 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002523 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002524 char *errmsg = NULL;
2525
Willy Tarreaub099aca2008-10-12 17:26:37 +02002526 if (curproxy == &defproxy) {
2527 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002530 }
2531
Willy Tarreauef6494c2010-01-28 17:12:36 +01002532 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002533 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2534 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002537 }
2538
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002539 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2540 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2541 file, linenum, errmsg);
2542 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002545 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002546
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002547 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002548 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002549 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002550 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002551 struct redirect_rule *rule;
2552 int cur_arg;
2553 int type = REDIRECT_TYPE_NONE;
2554 int code = 302;
2555 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002556 char *cookie = NULL;
2557 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002558 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002559
Cyril Bonté99ed3272010-01-24 23:29:44 +01002560 if (curproxy == &defproxy) {
2561 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2562 err_code |= ERR_ALERT | ERR_FATAL;
2563 goto out;
2564 }
2565
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002566 cur_arg = 1;
2567 while (*(args[cur_arg])) {
2568 if (!strcmp(args[cur_arg], "location")) {
2569 if (!*args[cur_arg + 1]) {
2570 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2571 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002574 }
2575
2576 type = REDIRECT_TYPE_LOCATION;
2577 cur_arg++;
2578 destination = args[cur_arg];
2579 }
2580 else if (!strcmp(args[cur_arg], "prefix")) {
2581 if (!*args[cur_arg + 1]) {
2582 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2583 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002586 }
2587
2588 type = REDIRECT_TYPE_PREFIX;
2589 cur_arg++;
2590 destination = args[cur_arg];
2591 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002592 else if (!strcmp(args[cur_arg], "set-cookie")) {
2593 if (!*args[cur_arg + 1]) {
2594 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2595 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002598 }
2599
2600 cur_arg++;
2601 cookie = args[cur_arg];
2602 cookie_set = 1;
2603 }
2604 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2605 if (!*args[cur_arg + 1]) {
2606 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2607 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002610 }
2611
2612 cur_arg++;
2613 cookie = args[cur_arg];
2614 cookie_set = 0;
2615 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002616 else if (!strcmp(args[cur_arg],"code")) {
2617 if (!*args[cur_arg + 1]) {
2618 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002622 }
2623 cur_arg++;
2624 code = atol(args[cur_arg]);
2625 if (code < 301 || code > 303) {
2626 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2627 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002630 }
2631 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002632 else if (!strcmp(args[cur_arg],"drop-query")) {
2633 flags |= REDIRECT_FLAG_DROP_QS;
2634 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002635 else if (!strcmp(args[cur_arg],"append-slash")) {
2636 flags |= REDIRECT_FLAG_APPEND_SLASH;
2637 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002638 else if (strcmp(args[cur_arg], "if") == 0 ||
2639 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002640 char *errmsg = NULL;
2641
2642 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002643 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002644 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2645 file, linenum, args[0], errmsg);
2646 free(errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
2649 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002650 break;
2651 }
2652 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002653 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 +02002654 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002657 }
2658 cur_arg++;
2659 }
2660
2661 if (type == REDIRECT_TYPE_NONE) {
2662 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2663 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002666 }
2667
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002668 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2669 rule->cond = cond;
2670 rule->rdr_str = strdup(destination);
2671 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002672 if (cookie) {
2673 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002674 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002675 */
2676 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002677 if (cookie_set) {
2678 rule->cookie_str = malloc(rule->cookie_len + 10);
2679 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2680 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2681 rule->cookie_len += 9;
2682 } else {
2683 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002684 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002685 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2686 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002687 }
2688 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002689 rule->type = type;
2690 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002691 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002692 LIST_INIT(&rule->list);
2693 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002694 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2695 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002696 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002697 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002698 struct switching_rule *rule;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002699 char *errmsg = NULL;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002700
Willy Tarreaub099aca2008-10-12 17:26:37 +02002701 if (curproxy == &defproxy) {
2702 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002705 }
2706
Willy Tarreau55ea7572007-06-17 19:56:27 +02002707 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002709
2710 if (*(args[1]) == 0) {
2711 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002714 }
2715
Willy Tarreauef6494c2010-01-28 17:12:36 +01002716 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002717 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2718 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002721 }
2722
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002723 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2724 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2725 file, linenum, errmsg);
2726 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002729 }
2730
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002731 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002732
Willy Tarreau55ea7572007-06-17 19:56:27 +02002733 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2734 rule->cond = cond;
2735 rule->be.name = strdup(args[1]);
2736 LIST_INIT(&rule->list);
2737 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2738 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002739 else if (strcmp(args[0], "use-server") == 0) {
2740 struct server_rule *rule;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002741 char *errmsg = NULL;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002742
2743 if (curproxy == &defproxy) {
2744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748
2749 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2750 err_code |= ERR_WARN;
2751
2752 if (*(args[1]) == 0) {
2753 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
2756 }
2757
2758 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2759 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2760 file, linenum, args[0]);
2761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
2763 }
2764
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002765 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2766 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2767 file, linenum, errmsg);
2768 free(errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
2772
2773 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2774
2775 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2776 rule->cond = cond;
2777 rule->srv.name = strdup(args[1]);
2778 LIST_INIT(&rule->list);
2779 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2780 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2781 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002782 else if ((!strcmp(args[0], "force-persist")) ||
2783 (!strcmp(args[0], "ignore-persist"))) {
2784 struct persist_rule *rule;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002785 char *errmsg = NULL;
Willy Tarreau4de91492010-01-22 19:10:05 +01002786
2787 if (curproxy == &defproxy) {
2788 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
2791 }
2792
2793 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2794 err_code |= ERR_WARN;
2795
Willy Tarreauef6494c2010-01-28 17:12:36 +01002796 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002797 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2798 file, linenum, args[0]);
2799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
2801 }
2802
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002803 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2804 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2805 file, linenum, args[0], errmsg);
2806 free(errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002807 err_code |= ERR_ALERT | ERR_FATAL;
2808 goto out;
2809 }
2810
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002811 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002812
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002813 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002814 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002815 if (!strcmp(args[0], "force-persist")) {
2816 rule->type = PERSIST_TYPE_FORCE;
2817 } else {
2818 rule->type = PERSIST_TYPE_IGNORE;
2819 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002820 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002821 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002822 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002823 else if (!strcmp(args[0], "stick-table")) {
2824 int myidx = 1;
2825
Emeric Brun32da3c42010-09-23 18:39:19 +02002826 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002827 curproxy->table.type = (unsigned int)-1;
2828 while (*args[myidx]) {
2829 const char *err;
2830
2831 if (strcmp(args[myidx], "size") == 0) {
2832 myidx++;
2833 if (!*(args[myidx])) {
2834 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2835 file, linenum, args[myidx-1]);
2836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
2838 }
2839 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2840 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2841 file, linenum, *err, args[myidx-1]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
2844 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002845 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002846 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002847 else if (strcmp(args[myidx], "peers") == 0) {
2848 myidx++;
2849 if (!*(args[myidx])) {
2850 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2851 file, linenum, args[myidx-1]);
2852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
2854 }
2855 curproxy->table.peers.name = strdup(args[myidx++]);
2856 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002857 else if (strcmp(args[myidx], "expire") == 0) {
2858 myidx++;
2859 if (!*(args[myidx])) {
2860 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2861 file, linenum, args[myidx-1]);
2862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
2864 }
2865 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2866 if (err) {
2867 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2868 file, linenum, *err, args[myidx-1]);
2869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002873 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002874 }
2875 else if (strcmp(args[myidx], "nopurge") == 0) {
2876 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002877 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002878 }
2879 else if (strcmp(args[myidx], "type") == 0) {
2880 myidx++;
2881 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2882 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2883 file, linenum, args[myidx]);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002887 /* myidx already points to next arg */
2888 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002889 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002890 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002891 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002892
2893 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002894 nw = args[myidx];
2895 while (*nw) {
2896 /* the "store" keyword supports a comma-separated list */
2897 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002898 sa = NULL; /* store arg */
2899 while (*nw && *nw != ',') {
2900 if (*nw == '(') {
2901 *nw = 0;
2902 sa = ++nw;
2903 while (*nw != ')') {
2904 if (!*nw) {
2905 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2906 file, linenum, args[0], cw);
2907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
2909 }
2910 nw++;
2911 }
2912 *nw = '\0';
2913 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002914 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002915 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002916 if (*nw)
2917 *nw++ = '\0';
2918 type = stktable_get_data_type(cw);
2919 if (type < 0) {
2920 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2921 file, linenum, args[0], cw);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
Willy Tarreauac782882010-06-20 10:41:54 +02002925
2926 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2927 switch (err) {
2928 case PE_NONE: break;
2929 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002930 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2931 file, linenum, args[0], cw);
2932 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002933 break;
2934
2935 case PE_ARG_MISSING:
2936 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2937 file, linenum, args[0], cw);
2938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
2940
2941 case PE_ARG_NOT_USED:
2942 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2943 file, linenum, args[0], cw);
2944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
2946
2947 default:
2948 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2949 file, linenum, args[0], cw);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002952 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002953 }
2954 myidx++;
2955 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002956 else {
2957 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2958 file, linenum, args[myidx]);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002961 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002962 }
2963
2964 if (!curproxy->table.size) {
2965 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2966 file, linenum);
2967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
2969 }
2970
2971 if (curproxy->table.type == (unsigned int)-1) {
2972 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2973 file, linenum);
2974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
2976 }
2977 }
2978 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002979 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002980 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002981 int myidx = 0;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002982 char *errmsg = NULL;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002983 const char *name = NULL;
2984 int flags;
2985
2986 if (curproxy == &defproxy) {
2987 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991
2992 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2993 err_code |= ERR_WARN;
2994 goto out;
2995 }
2996
2997 myidx++;
2998 if ((strcmp(args[myidx], "store") == 0) ||
2999 (strcmp(args[myidx], "store-request") == 0)) {
3000 myidx++;
3001 flags = STK_IS_STORE;
3002 }
3003 else if (strcmp(args[myidx], "store-response") == 0) {
3004 myidx++;
3005 flags = STK_IS_STORE | STK_ON_RSP;
3006 }
3007 else if (strcmp(args[myidx], "match") == 0) {
3008 myidx++;
3009 flags = STK_IS_MATCH;
3010 }
3011 else if (strcmp(args[myidx], "on") == 0) {
3012 myidx++;
3013 flags = STK_IS_MATCH | STK_IS_STORE;
3014 }
3015 else {
3016 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020
3021 if (*(args[myidx]) == 0) {
3022 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
3025 }
3026
Willy Tarreau12785782012-04-27 21:37:17 +02003027 expr = sample_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003028 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003029 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
3033
3034 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003035 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003036 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3037 file, linenum, args[0], expr->fetch->kw);
3038 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003039 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003040 goto out;
3041 }
3042 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003043 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003044 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3045 file, linenum, args[0], expr->fetch->kw);
3046 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003047 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 goto out;
3049 }
3050 }
3051
3052 if (strcmp(args[myidx], "table") == 0) {
3053 myidx++;
3054 name = args[myidx++];
3055 }
3056
Willy Tarreauef6494c2010-01-28 17:12:36 +01003057 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003058 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3059 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3060 file, linenum, args[0], errmsg);
3061 free(errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003062 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003063 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003064 goto out;
3065 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003066 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003067 else if (*(args[myidx])) {
3068 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3069 file, linenum, args[0], args[myidx]);
3070 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003071 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003072 goto out;
3073 }
Emeric Brun97679e72010-09-23 17:56:44 +02003074 if (flags & STK_ON_RSP)
3075 err_code |= warnif_cond_requires_req(cond, file, linenum);
3076 else
3077 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003078
Emeric Brunb982a3d2010-01-04 15:45:53 +01003079 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3080 rule->cond = cond;
3081 rule->expr = expr;
3082 rule->flags = flags;
3083 rule->table.name = name ? strdup(name) : NULL;
3084 LIST_INIT(&rule->list);
3085 if (flags & STK_ON_RSP)
3086 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3087 else
3088 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3089 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003091 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003093
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3095 curproxy->uri_auth = NULL; /* we must detach from the default config */
3096
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003097 if (!*args[1]) {
3098 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003099 } else if (!strcmp(args[1], "admin")) {
3100 struct stats_admin_rule *rule;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003101 char *errmsg = NULL;
Cyril Bonté474be412010-10-12 00:14:36 +02003102
3103 if (curproxy == &defproxy) {
3104 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
3107 }
3108
3109 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3110 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3111 err_code |= ERR_ALERT | ERR_ABORT;
3112 goto out;
3113 }
3114
3115 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3116 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3117 file, linenum, args[0], args[1]);
3118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
3120 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003121 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3122 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3123 file, linenum, args[0], args[1], errmsg);
3124 free(errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127 }
3128
3129 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3130
3131 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3132 rule->cond = cond;
3133 LIST_INIT(&rule->list);
3134 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 } else if (!strcmp(args[1], "uri")) {
3136 if (*(args[2]) == 0) {
3137 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3141 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_ALERT | ERR_ABORT;
3143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 }
3145 } else if (!strcmp(args[1], "realm")) {
3146 if (*(args[2]) == 0) {
3147 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3151 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_ABORT;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003155 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003156 unsigned interval;
3157
3158 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3159 if (err) {
3160 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3161 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003164 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3165 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_ABORT;
3167 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003168 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003169 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003170 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003171
3172 if (curproxy == &defproxy) {
3173 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
3176 }
3177
3178 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3179 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3180 err_code |= ERR_ALERT | ERR_ABORT;
3181 goto out;
3182 }
3183
Willy Tarreauff011f22011-01-06 17:51:27 +01003184 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3185 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003186 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3187 file, linenum, args[0]);
3188 err_code |= ERR_WARN;
3189 }
3190
Willy Tarreauff011f22011-01-06 17:51:27 +01003191 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003192
Willy Tarreauff011f22011-01-06 17:51:27 +01003193 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003194 err_code |= ERR_ALERT | ERR_ABORT;
3195 goto out;
3196 }
3197
Willy Tarreauff011f22011-01-06 17:51:27 +01003198 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3199 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003200
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 } else if (!strcmp(args[1], "auth")) {
3202 if (*(args[2]) == 0) {
3203 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3207 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_ALERT | ERR_ABORT;
3209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
3211 } else if (!strcmp(args[1], "scope")) {
3212 if (*(args[2]) == 0) {
3213 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_ABORT;
3219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 }
3221 } else if (!strcmp(args[1], "enable")) {
3222 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_ABORT;
3225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003227 } else if (!strcmp(args[1], "hide-version")) {
3228 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3229 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_ABORT;
3231 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003232 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003233 } else if (!strcmp(args[1], "show-legends")) {
3234 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3235 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3236 err_code |= ERR_ALERT | ERR_ABORT;
3237 goto out;
3238 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003239 } else if (!strcmp(args[1], "show-node")) {
3240
3241 if (*args[2]) {
3242 int i;
3243 char c;
3244
3245 for (i=0; args[2][i]; i++) {
3246 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003247 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3248 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003249 break;
3250 }
3251
3252 if (!i || args[2][i]) {
3253 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3254 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3255 file, linenum, args[0], args[1]);
3256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
3258 }
3259 }
3260
3261 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3262 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3263 err_code |= ERR_ALERT | ERR_ABORT;
3264 goto out;
3265 }
3266 } else if (!strcmp(args[1], "show-desc")) {
3267 char *desc = NULL;
3268
3269 if (*args[2]) {
3270 int i, len=0;
3271 char *d;
3272
3273 for(i=2; *args[i]; i++)
3274 len += strlen(args[i])+1;
3275
3276 desc = d = (char *)calloc(1, len);
3277
3278 d += sprintf(d, "%s", args[2]);
3279 for(i=3; *args[i]; i++)
3280 d += sprintf(d, " %s", args[i]);
3281 }
3282
3283 if (!*args[2] && !global.desc)
3284 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3285 file, linenum, args[1]);
3286 else {
3287 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3288 free(desc);
3289 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3290 err_code |= ERR_ALERT | ERR_ABORT;
3291 goto out;
3292 }
3293 free(desc);
3294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003296stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003297 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 +01003298 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 }
3302 }
3303 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003304 int optnum;
3305
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003306 if (*(args[1]) == '\0') {
3307 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3308 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003312
3313 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3314 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003315 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3316 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3317 file, linenum, cfg_opts[optnum].name);
3318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
3320 }
Willy Tarreau93893792009-07-23 13:19:11 +02003321 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3322 err_code |= ERR_WARN;
3323 goto out;
3324 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003325
Willy Tarreau3842f002009-06-14 11:39:52 +02003326 curproxy->no_options &= ~cfg_opts[optnum].val;
3327 curproxy->options &= ~cfg_opts[optnum].val;
3328
3329 switch (kwm) {
3330 case KWM_STD:
3331 curproxy->options |= cfg_opts[optnum].val;
3332 break;
3333 case KWM_NO:
3334 curproxy->no_options |= cfg_opts[optnum].val;
3335 break;
3336 case KWM_DEF: /* already cleared */
3337 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003338 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003339
Willy Tarreau93893792009-07-23 13:19:11 +02003340 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003341 }
3342 }
3343
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003344 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3345 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003346 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3347 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3348 file, linenum, cfg_opts2[optnum].name);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
Willy Tarreau93893792009-07-23 13:19:11 +02003352 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3353 err_code |= ERR_WARN;
3354 goto out;
3355 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003356
Willy Tarreau3842f002009-06-14 11:39:52 +02003357 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3358 curproxy->options2 &= ~cfg_opts2[optnum].val;
3359
3360 switch (kwm) {
3361 case KWM_STD:
3362 curproxy->options2 |= cfg_opts2[optnum].val;
3363 break;
3364 case KWM_NO:
3365 curproxy->no_options2 |= cfg_opts2[optnum].val;
3366 break;
3367 case KWM_DEF: /* already cleared */
3368 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003369 }
Willy Tarreau93893792009-07-23 13:19:11 +02003370 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003371 }
3372 }
3373
Willy Tarreau3842f002009-06-14 11:39:52 +02003374 if (kwm != KWM_STD) {
3375 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003376 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003379 }
3380
Emeric Brun3a058f32009-06-30 18:26:00 +02003381 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003382 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003384 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003385 if (*(args[2]) != '\0') {
3386 if (!strcmp(args[2], "clf")) {
3387 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003388 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003389 } else {
3390 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003393 }
3394 }
William Lallemand1d705562012-03-12 12:46:41 +01003395 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
Emeric Brun3a058f32009-06-30 18:26:00 +02003396 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003397 else if (!strcmp(args[1], "tcplog")) {
3398 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 /* generate a detailed TCP log */
William Lallemandbddd4fd2012-02-27 11:23:10 +01003400 logformat = default_tcp_log_format;
William Lallemand1d705562012-03-12 12:46:41 +01003401 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
William Lallemandbddd4fd2012-02-27 11:23:10 +01003402 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 else if (!strcmp(args[1], "tcpka")) {
3404 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003405 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003407
3408 if (curproxy->cap & PR_CAP_FE)
3409 curproxy->options |= PR_O_TCP_CLI_KA;
3410 if (curproxy->cap & PR_CAP_BE)
3411 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
3413 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003414 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_WARN;
3416
Willy Tarreaubaaee002006-06-26 02:48:02 +02003417 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003418 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003419 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003420 curproxy->options2 &= ~PR_O2_CHK_ANY;
3421 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003422 if (!*args[2]) { /* no argument */
3423 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3424 curproxy->check_len = strlen(DEF_CHECK_REQ);
3425 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003426 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 curproxy->check_req = (char *)malloc(reqlen);
3428 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003429 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003430 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003431 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 if (*args[4])
3433 reqlen += strlen(args[4]);
3434 else
3435 reqlen += strlen("HTTP/1.0");
3436
3437 curproxy->check_req = (char *)malloc(reqlen);
3438 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003439 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003440 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003441 }
3442 else if (!strcmp(args[1], "ssl-hello-chk")) {
3443 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003444 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003445 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003446
Willy Tarreaua534fea2008-08-03 12:19:50 +02003447 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003448 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003449 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003450 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 }
Willy Tarreau23677902007-05-08 23:50:35 +02003452 else if (!strcmp(args[1], "smtpchk")) {
3453 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003454 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003455 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003456 curproxy->options2 &= ~PR_O2_CHK_ANY;
3457 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003458
3459 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3460 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3461 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3462 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3463 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3464 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3465 curproxy->check_req = (char *)malloc(reqlen);
3466 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3467 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3468 } else {
3469 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3470 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3471 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3472 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3473 }
3474 }
3475 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003476 else if (!strcmp(args[1], "pgsql-check")) {
3477 /* use PostgreSQL request to check servers' health */
3478 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3479 err_code |= ERR_WARN;
3480
3481 free(curproxy->check_req);
3482 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003483 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003484 curproxy->options2 |= PR_O2_PGSQL_CHK;
3485
3486 if (*(args[2])) {
3487 int cur_arg = 2;
3488
3489 while (*(args[cur_arg])) {
3490 if (strcmp(args[cur_arg], "user") == 0) {
3491 char * packet;
3492 uint32_t packet_len;
3493 uint32_t pv;
3494
3495 /* suboption header - needs additional argument for it */
3496 if (*(args[cur_arg+1]) == 0) {
3497 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3498 file, linenum, args[0], args[1], args[cur_arg]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
3502
3503 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3504 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3505 pv = htonl(0x30000); /* protocol version 3.0 */
3506
3507 packet = (char*) calloc(1, packet_len);
3508
3509 memcpy(packet + 4, &pv, 4);
3510
3511 /* copy "user" */
3512 memcpy(packet + 8, "user", 4);
3513
3514 /* copy username */
3515 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3516
3517 free(curproxy->check_req);
3518 curproxy->check_req = packet;
3519 curproxy->check_len = packet_len;
3520
3521 packet_len = htonl(packet_len);
3522 memcpy(packet, &packet_len, 4);
3523 cur_arg += 2;
3524 } else {
3525 /* unknown suboption - catchall */
3526 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3527 file, linenum, args[0], args[1]);
3528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531 } /* end while loop */
3532 }
3533 }
3534
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003535 else if (!strcmp(args[1], "redis-check")) {
3536 /* use REDIS PING request to check servers' health */
3537 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3538 err_code |= ERR_WARN;
3539
3540 free(curproxy->check_req);
3541 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003542 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003543 curproxy->options2 |= PR_O2_REDIS_CHK;
3544
3545 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3546 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3547 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3548 }
3549
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003550 else if (!strcmp(args[1], "mysql-check")) {
3551 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003552 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3553 err_code |= ERR_WARN;
3554
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003555 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003556 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003557 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003558 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003559
3560 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3561 * const char mysql40_client_auth_pkt[] = {
3562 * "\x0e\x00\x00" // packet length
3563 * "\x01" // packet number
3564 * "\x00\x00" // client capabilities
3565 * "\x00\x00\x01" // max packet
3566 * "haproxy\x00" // username (null terminated string)
3567 * "\x00" // filler (always 0x00)
3568 * "\x01\x00\x00" // packet length
3569 * "\x00" // packet number
3570 * "\x01" // COM_QUIT command
3571 * };
3572 */
3573
3574 if (*(args[2])) {
3575 int cur_arg = 2;
3576
3577 while (*(args[cur_arg])) {
3578 if (strcmp(args[cur_arg], "user") == 0) {
3579 char *mysqluser;
3580 int packetlen, reqlen, userlen;
3581
3582 /* suboption header - needs additional argument for it */
3583 if (*(args[cur_arg+1]) == 0) {
3584 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3585 file, linenum, args[0], args[1], args[cur_arg]);
3586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
3588 }
3589 mysqluser = args[cur_arg + 1];
3590 userlen = strlen(mysqluser);
3591 packetlen = userlen + 7;
3592 reqlen = packetlen + 9;
3593
3594 free(curproxy->check_req);
3595 curproxy->check_req = (char *)calloc(1, reqlen);
3596 curproxy->check_len = reqlen;
3597
3598 snprintf(curproxy->check_req, 4, "%c%c%c",
3599 ((unsigned char) packetlen & 0xff),
3600 ((unsigned char) (packetlen >> 8) & 0xff),
3601 ((unsigned char) (packetlen >> 16) & 0xff));
3602
3603 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003604 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003605 curproxy->check_req[8] = 1;
3606 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3607 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3608 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3609 cur_arg += 2;
3610 } else {
3611 /* unknown suboption - catchall */
3612 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3613 file, linenum, args[0], args[1]);
3614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
3616 }
3617 } /* end while loop */
3618 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003619 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003620 else if (!strcmp(args[1], "ldap-check")) {
3621 /* use LDAP request to check servers' health */
3622 free(curproxy->check_req);
3623 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003624 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003625 curproxy->options2 |= PR_O2_LDAP_CHK;
3626
3627 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3628 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3629 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3630 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003631 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003632 int cur_arg;
3633
3634 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3635 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003636 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003637
Willy Tarreau87cf5142011-08-19 22:57:24 +02003638 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003639
3640 free(curproxy->fwdfor_hdr_name);
3641 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3642 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3643
3644 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3645 cur_arg = 2;
3646 while (*(args[cur_arg])) {
3647 if (!strcmp(args[cur_arg], "except")) {
3648 /* suboption except - needs additional argument for it */
3649 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3650 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3651 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003654 }
3655 /* flush useless bits */
3656 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003657 cur_arg += 2;
3658 } else if (!strcmp(args[cur_arg], "header")) {
3659 /* suboption header - needs additional argument for it */
3660 if (*(args[cur_arg+1]) == 0) {
3661 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3662 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003665 }
3666 free(curproxy->fwdfor_hdr_name);
3667 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3668 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3669 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003670 } else if (!strcmp(args[cur_arg], "if-none")) {
3671 curproxy->options &= ~PR_O_FF_ALWAYS;
3672 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003673 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003674 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003675 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003676 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003679 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003680 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003681 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003682 else if (!strcmp(args[1], "originalto")) {
3683 int cur_arg;
3684
3685 /* insert x-original-to field, but not for the IP address listed as an except.
3686 * set default options (ie: bitfield, header name, etc)
3687 */
3688
3689 curproxy->options |= PR_O_ORGTO;
3690
3691 free(curproxy->orgto_hdr_name);
3692 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3693 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3694
Willy Tarreau87cf5142011-08-19 22:57:24 +02003695 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003696 cur_arg = 2;
3697 while (*(args[cur_arg])) {
3698 if (!strcmp(args[cur_arg], "except")) {
3699 /* suboption except - needs additional argument for it */
3700 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3701 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3702 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003705 }
3706 /* flush useless bits */
3707 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3708 cur_arg += 2;
3709 } else if (!strcmp(args[cur_arg], "header")) {
3710 /* suboption header - needs additional argument for it */
3711 if (*(args[cur_arg+1]) == 0) {
3712 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3713 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003716 }
3717 free(curproxy->orgto_hdr_name);
3718 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3719 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3720 cur_arg += 2;
3721 } else {
3722 /* unknown suboption - catchall */
3723 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3724 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003727 }
3728 } /* end while loop */
3729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 else {
3731 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 }
Willy Tarreau93893792009-07-23 13:19:11 +02003735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003737 else if (!strcmp(args[0], "default_backend")) {
3738 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003740
3741 if (*(args[1]) == 0) {
3742 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_ALERT | ERR_FATAL;
3744 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003745 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003746 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003747 curproxy->defbe.name = strdup(args[1]);
3748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003749 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003752
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003753 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3754 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 /* enable reconnections to dispatch */
3757 curproxy->options |= PR_O_REDISP;
3758 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003759 else if (!strcmp(args[0], "http-check")) {
3760 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003762
3763 if (strcmp(args[1], "disable-on-404") == 0) {
3764 /* enable a graceful server shutdown on an HTTP 404 response */
3765 curproxy->options |= PR_O_DISABLE404;
3766 }
Willy Tarreauef781042010-01-27 11:53:01 +01003767 else if (strcmp(args[1], "send-state") == 0) {
3768 /* enable emission of the apparent state of a server in HTTP checks */
3769 curproxy->options2 |= PR_O2_CHK_SNDST;
3770 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003771 else if (strcmp(args[1], "expect") == 0) {
3772 const char *ptr_arg;
3773 int cur_arg;
3774
3775 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3776 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
3779 }
3780
3781 cur_arg = 2;
3782 /* consider exclamation marks, sole or at the beginning of a word */
3783 while (*(ptr_arg = args[cur_arg])) {
3784 while (*ptr_arg == '!') {
3785 curproxy->options2 ^= PR_O2_EXP_INV;
3786 ptr_arg++;
3787 }
3788 if (*ptr_arg)
3789 break;
3790 cur_arg++;
3791 }
3792 /* now ptr_arg points to the beginning of a word past any possible
3793 * exclamation mark, and cur_arg is the argument which holds this word.
3794 */
3795 if (strcmp(ptr_arg, "status") == 0) {
3796 if (!*(args[cur_arg + 1])) {
3797 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3798 file, linenum, args[0], args[1], ptr_arg);
3799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
3801 }
3802 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003803 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003804 curproxy->expect_str = strdup(args[cur_arg + 1]);
3805 }
3806 else if (strcmp(ptr_arg, "string") == 0) {
3807 if (!*(args[cur_arg + 1])) {
3808 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3809 file, linenum, args[0], args[1], ptr_arg);
3810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
3812 }
3813 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003814 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003815 curproxy->expect_str = strdup(args[cur_arg + 1]);
3816 }
3817 else if (strcmp(ptr_arg, "rstatus") == 0) {
3818 if (!*(args[cur_arg + 1])) {
3819 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3820 file, linenum, args[0], args[1], ptr_arg);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003825 free(curproxy->expect_str);
3826 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3827 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003828 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3829 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3830 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3831 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835 }
3836 else if (strcmp(ptr_arg, "rstring") == 0) {
3837 if (!*(args[cur_arg + 1])) {
3838 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3839 file, linenum, args[0], args[1], ptr_arg);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003844 free(curproxy->expect_str);
3845 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3846 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003847 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3848 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3849 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3850 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
3853 }
3854 }
3855 else {
3856 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3857 file, linenum, args[0], args[1], ptr_arg);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003862 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003863 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003866 }
3867 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003868 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003869 if (curproxy == &defproxy) {
3870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003873 }
3874
Willy Tarreaub80c2302007-11-30 20:51:32 +01003875 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003877
3878 if (strcmp(args[1], "fail") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003879 char *errmsg = NULL;
3880
Willy Tarreaub80c2302007-11-30 20:51:32 +01003881 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003882 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003883 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3884 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003887 }
3888
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003889 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3890 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3891 file, linenum, args[0], args[1], errmsg);
3892 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003895 }
3896 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3897 }
3898 else {
3899 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003900 err_code |= ERR_ALERT | ERR_FATAL;
3901 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003902 }
3903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904#ifdef TPROXY
3905 else if (!strcmp(args[0], "transparent")) {
3906 /* enable transparent proxy connections */
3907 curproxy->options |= PR_O_TRANSP;
3908 }
3909#endif
3910 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003911 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003912 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003913
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914 if (*(args[1]) == 0) {
3915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003918 }
3919 curproxy->maxconn = atol(args[1]);
3920 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003921 else if (!strcmp(args[0], "backlog")) { /* backlog */
3922 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003923 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003924
3925 if (*(args[1]) == 0) {
3926 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003929 }
3930 curproxy->backlog = atol(args[1]);
3931 }
Willy Tarreau86034312006-12-29 00:10:33 +01003932 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003933 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003934 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003935
Willy Tarreau86034312006-12-29 00:10:33 +01003936 if (*(args[1]) == 0) {
3937 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003940 }
3941 curproxy->fullconn = atol(args[1]);
3942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3944 if (*(args[1]) == 0) {
3945 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003949 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3950 if (err) {
3951 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3952 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003955 }
3956 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003957 }
3958 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003959 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 if (curproxy == &defproxy) {
3961 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003962 err_code |= ERR_ALERT | ERR_FATAL;
3963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003965 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003967
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 if (strchr(args[1], ':') == NULL) {
3969 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003972 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003973 sk = str2sa(args[1]);
3974 if (!sk) {
3975 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
3978 }
3979 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003980 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 }
3982 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003983 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003985
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003986 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003987 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3988 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003993 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3994 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3995 err_code |= ERR_WARN;
3996
3997 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3998 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3999 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4000 }
4001 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4002 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4003 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4004 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004005 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4006 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4007 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4008 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004009 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004010 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
4013 }
4014 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004015 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004016 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004017 char *rport, *raddr;
4018 short realport = 0;
4019 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004020
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004021 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004026 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004028
4029 if (!*args[2]) {
4030 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4031 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004034 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004035
4036 err = invalid_char(args[1]);
4037 if (err) {
4038 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4039 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004042 }
4043
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004044 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004045 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004046
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004047 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4048 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4049 err_code |= ERR_ALERT | ERR_ABORT;
4050 goto out;
4051 }
4052
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004053 /* the servers are linked backwards first */
4054 newsrv->next = curproxy->srv;
4055 curproxy->srv = newsrv;
4056 newsrv->proxy = curproxy;
4057 newsrv->conf.file = file;
4058 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059
Simon Hormanaf514952011-06-21 14:34:57 +09004060 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004061 LIST_INIT(&newsrv->pendconns);
4062 do_check = 0;
4063 newsrv->state = SRV_RUNNING; /* early server setup */
4064 newsrv->last_change = now.tv_sec;
4065 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004066
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004067 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004068 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004069 * - IP: => port=+0, relative
4070 * - IP:N => port=N, absolute
4071 * - IP:+N => port=+N, relative
4072 * - IP:-N => port=-N, relative
4073 */
4074 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004075 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004076 if (rport) {
4077 *rport++ = 0;
4078 realport = atol(rport);
4079 if (!isdigit((unsigned char)*rport))
4080 newsrv->state |= SRV_MAPPORTS;
4081 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004082 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004083
Willy Tarreaufab5a432011-03-04 15:31:53 +01004084 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004085 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004086 if (!sk) {
4087 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
4090 }
4091 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004092 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
4093
4094 if (!sk) {
4095 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4096 file, linenum, newsrv->addr.ss_family, args[2]);
4097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004100 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004101
4102 newsrv->check_port = curproxy->defsrv.check_port;
4103 newsrv->inter = curproxy->defsrv.inter;
4104 newsrv->fastinter = curproxy->defsrv.fastinter;
4105 newsrv->downinter = curproxy->defsrv.downinter;
4106 newsrv->rise = curproxy->defsrv.rise;
4107 newsrv->fall = curproxy->defsrv.fall;
4108 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4109 newsrv->minconn = curproxy->defsrv.minconn;
4110 newsrv->maxconn = curproxy->defsrv.maxconn;
4111 newsrv->slowstart = curproxy->defsrv.slowstart;
4112 newsrv->onerror = curproxy->defsrv.onerror;
4113 newsrv->consecutive_errors_limit
4114 = curproxy->defsrv.consecutive_errors_limit;
4115 newsrv->uweight = newsrv->iweight
4116 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004117
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004118 newsrv->curfd = -1; /* no health-check in progress */
4119 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004121 cur_arg = 3;
4122 } else {
4123 newsrv = &curproxy->defsrv;
4124 cur_arg = 1;
4125 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004126
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004128 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004129 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004130
4131 if (!*args[cur_arg + 1]) {
4132 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4133 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004136 }
4137
4138 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004139 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004140
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004141 if (newsrv->puid <= 0) {
4142 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004143 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004146 }
4147
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004148 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4149 if (node) {
4150 struct server *target = container_of(node, struct server, conf.id);
4151 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4152 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
4155 }
4156 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004157 cur_arg += 2;
4158 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004159 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 newsrv->cookie = strdup(args[cur_arg + 1]);
4161 newsrv->cklen = strlen(args[cur_arg + 1]);
4162 cur_arg += 2;
4163 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004164 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004165 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4166 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4167 cur_arg += 2;
4168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004170 if (!*args[cur_arg + 1]) {
4171 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4172 file, linenum, args[cur_arg]);
4173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
4175 }
4176
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004178 if (newsrv->rise <= 0) {
4179 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4180 file, linenum, args[cur_arg]);
4181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
4183 }
4184
Willy Tarreau96839092010-03-29 10:02:24 +02004185 if (newsrv->health)
4186 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 cur_arg += 2;
4188 }
4189 else if (!strcmp(args[cur_arg], "fall")) {
4190 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004191
4192 if (!*args[cur_arg + 1]) {
4193 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4194 file, linenum, args[cur_arg]);
4195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
4197 }
4198
4199 if (newsrv->fall <= 0) {
4200 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4201 file, linenum, args[cur_arg]);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 }
4205
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206 cur_arg += 2;
4207 }
4208 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004209 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4210 if (err) {
4211 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4212 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004215 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004216 if (val <= 0) {
4217 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4218 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004221 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004222 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 cur_arg += 2;
4224 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004225 else if (!strcmp(args[cur_arg], "fastinter")) {
4226 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4227 if (err) {
4228 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4229 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004232 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004233 if (val <= 0) {
4234 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4235 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004238 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004239 newsrv->fastinter = val;
4240 cur_arg += 2;
4241 }
4242 else if (!strcmp(args[cur_arg], "downinter")) {
4243 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4244 if (err) {
4245 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4246 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004249 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004250 if (val <= 0) {
4251 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4252 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004255 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004256 newsrv->downinter = val;
4257 cur_arg += 2;
4258 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004259 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004260 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004261 if (!sk) {
4262 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265 }
4266 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004267 cur_arg += 2;
4268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004269 else if (!strcmp(args[cur_arg], "port")) {
4270 newsrv->check_port = atol(args[cur_arg + 1]);
4271 cur_arg += 2;
4272 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004273 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004274 newsrv->state |= SRV_BACKUP;
4275 cur_arg ++;
4276 }
Simon Hormanfa461682011-06-25 09:39:49 +09004277 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4278 newsrv->state |= SRV_NON_STICK;
4279 cur_arg ++;
4280 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004281 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4282 newsrv->state |= SRV_SEND_PROXY;
4283 cur_arg ++;
4284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 else if (!strcmp(args[cur_arg], "weight")) {
4286 int w;
4287 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004288 if (w < 0 || w > 256) {
4289 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004290 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004293 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004294 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 cur_arg += 2;
4296 }
4297 else if (!strcmp(args[cur_arg], "minconn")) {
4298 newsrv->minconn = atol(args[cur_arg + 1]);
4299 cur_arg += 2;
4300 }
4301 else if (!strcmp(args[cur_arg], "maxconn")) {
4302 newsrv->maxconn = atol(args[cur_arg + 1]);
4303 cur_arg += 2;
4304 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004305 else if (!strcmp(args[cur_arg], "maxqueue")) {
4306 newsrv->maxqueue = atol(args[cur_arg + 1]);
4307 cur_arg += 2;
4308 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004309 else if (!strcmp(args[cur_arg], "slowstart")) {
4310 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004311 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004312 if (err) {
4313 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4314 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004317 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004318 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004319 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4320 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004323 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004324 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004325 cur_arg += 2;
4326 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004327 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004328
4329 if (!*args[cur_arg + 1]) {
4330 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4331 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004334 }
4335
4336 newsrv->trackit = strdup(args[cur_arg + 1]);
4337
4338 cur_arg += 2;
4339 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004340 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004341 global.maxsock++;
4342 do_check = 1;
4343 cur_arg += 1;
4344 }
Willy Tarreau96839092010-03-29 10:02:24 +02004345 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4346 newsrv->state |= SRV_MAINTAIN;
4347 newsrv->state &= ~SRV_RUNNING;
4348 newsrv->health = 0;
4349 cur_arg += 1;
4350 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004351 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004352 if (!strcmp(args[cur_arg + 1], "none"))
4353 newsrv->observe = HANA_OBS_NONE;
4354 else if (!strcmp(args[cur_arg + 1], "layer4"))
4355 newsrv->observe = HANA_OBS_LAYER4;
4356 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4357 if (curproxy->mode != PR_MODE_HTTP) {
4358 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4359 file, linenum, args[cur_arg + 1]);
4360 err_code |= ERR_ALERT;
4361 }
4362 newsrv->observe = HANA_OBS_LAYER7;
4363 }
4364 else {
4365 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004366 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004367 file, linenum, args[cur_arg], args[cur_arg + 1]);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371
4372 cur_arg += 2;
4373 }
4374 else if (!strcmp(args[cur_arg], "on-error")) {
4375 if (!strcmp(args[cur_arg + 1], "fastinter"))
4376 newsrv->onerror = HANA_ONERR_FASTINTER;
4377 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4378 newsrv->onerror = HANA_ONERR_FAILCHK;
4379 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4380 newsrv->onerror = HANA_ONERR_SUDDTH;
4381 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4382 newsrv->onerror = HANA_ONERR_MARKDWN;
4383 else {
4384 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004385 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004386 file, linenum, args[cur_arg], args[cur_arg + 1]);
4387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
4389 }
4390
4391 cur_arg += 2;
4392 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004393 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4394 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4395 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4396 else {
4397 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4398 file, linenum, args[cur_arg], args[cur_arg + 1]);
4399 err_code |= ERR_ALERT | ERR_FATAL;
4400 goto out;
4401 }
4402
4403 cur_arg += 2;
4404 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004405 else if (!strcmp(args[cur_arg], "error-limit")) {
4406 if (!*args[cur_arg + 1]) {
4407 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4408 file, linenum, args[cur_arg]);
4409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
4411 }
4412
4413 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4414
4415 if (newsrv->consecutive_errors_limit <= 0) {
4416 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4417 file, linenum, args[cur_arg]);
4418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
4420 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004421 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004422 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004423 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004424 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004425 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004426
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004428#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004429 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004430 file, linenum, "source", "usesrc");
4431#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004432 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004433 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004434#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 }
4438 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004439 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4440 if (!sk) {
4441 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
4444 }
4445 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004446
4447 if (port_low != port_high) {
4448 int i;
4449 if (port_low <= 0 || port_low > 65535 ||
4450 port_high <= 0 || port_high > 65535 ||
4451 port_low > port_high) {
4452 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4453 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004454 err_code |= ERR_ALERT | ERR_FATAL;
4455 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004456 }
4457 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4458 for (i = 0; i < newsrv->sport_range->size; i++)
4459 newsrv->sport_range->ports[i] = port_low + i;
4460 }
4461
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004463 while (*(args[cur_arg])) {
4464 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004465#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4466#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004467 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4468 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4469 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004470 err_code |= ERR_ALERT | ERR_FATAL;
4471 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004472 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004473#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004474 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004475 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004476 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004479 }
4480 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004481 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004482 newsrv->state |= SRV_TPROXY_CLI;
4483 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004484 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004485 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004486 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4487 char *name, *end;
4488
4489 name = args[cur_arg+1] + 7;
4490 while (isspace(*name))
4491 name++;
4492
4493 end = name;
4494 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4495 end++;
4496
4497 newsrv->state &= ~SRV_TPROXY_MASK;
4498 newsrv->state |= SRV_TPROXY_DYN;
4499 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4500 newsrv->bind_hdr_len = end - name;
4501 memcpy(newsrv->bind_hdr_name, name, end - name);
4502 newsrv->bind_hdr_name[end-name] = '\0';
4503 newsrv->bind_hdr_occ = -1;
4504
4505 /* now look for an occurrence number */
4506 while (isspace(*end))
4507 end++;
4508 if (*end == ',') {
4509 end++;
4510 name = end;
4511 if (*end == '-')
4512 end++;
4513 while (isdigit(*end))
4514 end++;
4515 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4516 }
4517
4518 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4519 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4520 " occurrences values smaller than %d.\n",
4521 file, linenum, MAX_HDR_HISTORY);
4522 err_code |= ERR_ALERT | ERR_FATAL;
4523 goto out;
4524 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004525 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004526 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004527 if (!sk) {
4528 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
4531 }
4532 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004533 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004534 }
4535 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004536#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004537 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004538#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004539 cur_arg += 2;
4540 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004541#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004542 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004543 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004544 err_code |= ERR_ALERT | ERR_FATAL;
4545 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004546#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4547 } /* "usesrc" */
4548
4549 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4550#ifdef SO_BINDTODEVICE
4551 if (!*args[cur_arg + 1]) {
4552 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4553 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004556 }
4557 if (newsrv->iface_name)
4558 free(newsrv->iface_name);
4559
4560 newsrv->iface_name = strdup(args[cur_arg + 1]);
4561 newsrv->iface_len = strlen(newsrv->iface_name);
4562 global.last_checks |= LSTCHK_NETADM;
4563#else
4564 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4565 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004568#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004569 cur_arg += 2;
4570 continue;
4571 }
4572 /* this keyword in not an option of "source" */
4573 break;
4574 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004575 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004576 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004577 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4578 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004583 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004584 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'on-marked-down', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004585 file, linenum, newsrv->id);
4586 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004587 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 +01004588 file, linenum);
4589
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 }
4593 }
4594
4595 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004596 if (newsrv->trackit) {
4597 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4598 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004601 }
4602
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004603 /* try to get the port from check_addr if check_port not set */
4604 if (!newsrv->check_port)
4605 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004606
Willy Tarreaubaaee002006-06-26 02:48:02 +02004607 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4608 newsrv->check_port = realport; /* by default */
4609 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004610 /* not yet valid, because no port was set on
4611 * the server either. We'll check if we have
4612 * a known port on the first listener.
4613 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004614 struct listener *l = curproxy->listen;
4615 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4616 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004617 }
4618 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4620 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004624
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004625 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004626 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004627 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4628 err_code |= ERR_ALERT | ERR_ABORT;
4629 goto out;
4630 }
4631
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004632 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004633 newsrv->state |= SRV_CHECKED;
4634 }
4635
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004636 if (!defsrv) {
4637 if (newsrv->state & SRV_BACKUP)
4638 curproxy->srv_bck++;
4639 else
4640 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004641
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004642 newsrv->prev_state = newsrv->state;
4643 }
William Lallemanda73203e2012-03-12 12:48:57 +01004644 }
4645
4646 else if (strcmp(args[0], "unique-id-format") == 0) {
4647 if (!*(args[1])) {
4648 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4649 err_code |= ERR_ALERT | ERR_FATAL;
4650 goto out;
4651 }
4652 parse_logformat_string(args[1], curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
William Lallemand723b73a2012-02-08 16:37:49 +01004653 }
William Lallemanda73203e2012-03-12 12:48:57 +01004654
4655 else if (strcmp(args[0], "unique-id-header") == 0) {
4656 if (!*(args[1])) {
4657 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4658 err_code |= ERR_ALERT | ERR_FATAL;
4659 goto out;
4660 }
4661 free(curproxy->header_unique_id);
4662 curproxy->header_unique_id = strdup(args[1]);
4663 }
4664
William Lallemand723b73a2012-02-08 16:37:49 +01004665 else if (strcmp(args[0], "log-format") == 0) {
4666 if (!*(args[1])) {
4667 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4668 err_code |= ERR_ALERT | ERR_FATAL;
4669 goto out;
4670 }
William Lallemand1d705562012-03-12 12:46:41 +01004671 parse_logformat_string(args[1], curproxy, &curproxy->logformat, curproxy->mode);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 }
William Lallemand723b73a2012-02-08 16:37:49 +01004673
William Lallemand0f99e342011-10-12 17:50:54 +02004674 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4675 /* delete previous herited or defined syslog servers */
4676 struct logsrv *back;
4677
4678 if (*(args[1]) != 0) {
4679 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4680 err_code |= ERR_ALERT | ERR_FATAL;
4681 goto out;
4682 }
4683
William Lallemand723b73a2012-02-08 16:37:49 +01004684 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4685 LIST_DEL(&tmplogsrv->list);
4686 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004687 }
4688 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004689 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004690 struct logsrv *logsrv;
4691
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004693 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004694 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004695 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004696 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004697 LIST_INIT(&node->list);
4698 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 }
4701 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004702
4703 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704
William Lallemand0f99e342011-10-12 17:50:54 +02004705 logsrv->facility = get_log_facility(args[2]);
4706 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
4710
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711 }
4712
William Lallemand0f99e342011-10-12 17:50:54 +02004713 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004715 logsrv->level = get_log_level(args[3]);
4716 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 }
4722 }
4723
William Lallemand0f99e342011-10-12 17:50:54 +02004724 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004725 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004726 logsrv->minlvl = get_log_level(args[4]);
4727 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004728 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004729 err_code |= ERR_ALERT | ERR_FATAL;
4730 goto out;
4731
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004732 }
4733 }
4734
Robert Tsai81ae1952007-12-05 10:47:29 +01004735 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004736 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004737 if (!sk) {
4738 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004739 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
4742 }
William Lallemand0f99e342011-10-12 17:50:54 +02004743 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004744 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004745 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004746 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004747 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
4750 }
William Lallemand0f99e342011-10-12 17:50:54 +02004751 logsrv->addr = *sk;
4752 if (!get_host_port(&logsrv->addr))
4753 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754 }
William Lallemand0f99e342011-10-12 17:50:54 +02004755
4756 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
4758 else {
4759 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4760 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
4764 }
4765 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004766 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004767 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004768
Willy Tarreau977b8e42006-12-29 14:19:17 +01004769 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004770 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004771
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004773 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4774 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004778
4779 /* we must first clear any optional default setting */
4780 curproxy->options &= ~PR_O_TPXY_MASK;
4781 free(curproxy->iface_name);
4782 curproxy->iface_name = NULL;
4783 curproxy->iface_len = 0;
4784
Willy Tarreaud5191e72010-02-09 20:50:45 +01004785 sk = str2sa(args[1]);
4786 if (!sk) {
4787 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4788 err_code |= ERR_ALERT | ERR_FATAL;
4789 goto out;
4790 }
4791 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004793
4794 cur_arg = 2;
4795 while (*(args[cur_arg])) {
4796 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004797#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4798#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004799 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4800 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4801 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004804 }
4805#endif
4806 if (!*args[cur_arg + 1]) {
4807 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4808 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004809 err_code |= ERR_ALERT | ERR_FATAL;
4810 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004811 }
4812
4813 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004814 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004815 curproxy->options |= PR_O_TPXY_CLI;
4816 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004817 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004818 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004819 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4820 char *name, *end;
4821
4822 name = args[cur_arg+1] + 7;
4823 while (isspace(*name))
4824 name++;
4825
4826 end = name;
4827 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4828 end++;
4829
4830 curproxy->options &= ~PR_O_TPXY_MASK;
4831 curproxy->options |= PR_O_TPXY_DYN;
4832 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4833 curproxy->bind_hdr_len = end - name;
4834 memcpy(curproxy->bind_hdr_name, name, end - name);
4835 curproxy->bind_hdr_name[end-name] = '\0';
4836 curproxy->bind_hdr_occ = -1;
4837
4838 /* now look for an occurrence number */
4839 while (isspace(*end))
4840 end++;
4841 if (*end == ',') {
4842 end++;
4843 name = end;
4844 if (*end == '-')
4845 end++;
4846 while (isdigit(*end))
4847 end++;
4848 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4849 }
4850
4851 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4852 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4853 " occurrences values smaller than %d.\n",
4854 file, linenum, MAX_HDR_HISTORY);
4855 err_code |= ERR_ALERT | ERR_FATAL;
4856 goto out;
4857 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004858 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004859 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004860 if (!sk) {
4861 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
4864 }
4865 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004866 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004867 }
4868 global.last_checks |= LSTCHK_NETADM;
4869#if !defined(CONFIG_HAP_LINUX_TPROXY)
4870 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004871#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004872#else /* no TPROXY support */
4873 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004874 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004877#endif
4878 cur_arg += 2;
4879 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004880 }
4881
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004882 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4883#ifdef SO_BINDTODEVICE
4884 if (!*args[cur_arg + 1]) {
4885 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4886 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004887 err_code |= ERR_ALERT | ERR_FATAL;
4888 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004889 }
4890 if (curproxy->iface_name)
4891 free(curproxy->iface_name);
4892
4893 curproxy->iface_name = strdup(args[cur_arg + 1]);
4894 curproxy->iface_len = strlen(curproxy->iface_name);
4895 global.last_checks |= LSTCHK_NETADM;
4896#else
4897 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4898 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004899 err_code |= ERR_ALERT | ERR_FATAL;
4900 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004901#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004902 cur_arg += 2;
4903 continue;
4904 }
4905 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4906 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004911 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4912 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4913 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004914 err_code |= ERR_ALERT | ERR_FATAL;
4915 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004924
4925 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004926 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004927 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
4931 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004933 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004934 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 }
4938 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004940 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004941 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
4945 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004947 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004948 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004949 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004954 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004955 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004959 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004961 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004962 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004964 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004965 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004966 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004968 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004969 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004971 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004972 }
4973 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004975 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004976 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004978 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004979 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4983 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004987
4988 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004989 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004990 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
4994 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004996 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004997 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
5001 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005003 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005004 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 }
5008 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005010 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005011 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005012 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 }
5015 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005016 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005017 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005018 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005019 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005022 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005023 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005024 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005025 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005026 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005027 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005030 struct cond_wordlist *wl;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005031 char *errmsg = NULL;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005032
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 if (curproxy == &defproxy) {
5034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005038 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 if (*(args[1]) == 0) {
5042 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005046
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005047 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005048 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5049 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5050 file, linenum, args[0], errmsg);
5051 free(errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005052 err_code |= ERR_ALERT | ERR_FATAL;
5053 goto out;
5054 }
5055 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5056 }
5057 else if (*args[2]) {
5058 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5059 file, linenum, args[0], args[2]);
5060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
5062 }
5063
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005064 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005065 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005066 wl->s = strdup(args[1]);
5067 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005068 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005069 }
5070 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005072 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5073 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005077
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005079 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005080 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005081 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 }
5084 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005085 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005086 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005087 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005088 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 }
5091 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005092 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005093 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005094 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005095 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097 }
5098 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005099 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 }
5105
Willy Tarreauade5ec42010-01-28 19:33:49 +01005106 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005107 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005108 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 }
5112 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005113 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005114 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005115 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005116 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
5119 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005121 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005122 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005123 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 }
5126 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005127 struct cond_wordlist *wl;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005128 char *errmsg = NULL;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005129
Willy Tarreaubaaee002006-06-26 02:48:02 +02005130 if (curproxy == &defproxy) {
5131 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005134 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005135 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 if (*(args[1]) == 0) {
5139 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
5143
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005144 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005145 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5146 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5147 file, linenum, args[0], errmsg);
5148 free(errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
5151 }
5152 err_code |= warnif_cond_requires_req(cond, file, linenum);
5153 }
5154 else if (*args[2]) {
5155 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5156 file, linenum, args[0], args[2]);
5157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
5159 }
5160
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005161 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005162 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005163 wl->s = strdup(args[1]);
5164 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 }
5166 else if (!strcmp(args[0], "errorloc") ||
5167 !strcmp(args[0], "errorloc302") ||
5168 !strcmp(args[0], "errorloc303")) { /* error location */
5169 int errnum, errlen;
5170 char *err;
5171
Willy Tarreau977b8e42006-12-29 14:19:17 +01005172 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005173 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005174
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005176 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
5180
5181 errnum = atol(args[1]);
5182 if (!strcmp(args[0], "errorloc303")) {
5183 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5184 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5185 } else {
5186 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5187 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5188 }
5189
Willy Tarreau0f772532006-12-23 20:51:41 +01005190 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5191 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005192 chunk_destroy(&curproxy->errmsg[rc]);
5193 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005194 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005197
5198 if (rc >= HTTP_ERR_SIZE) {
5199 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5200 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 free(err);
5202 }
5203 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005204 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5205 int errnum, errlen, fd;
5206 char *err;
5207 struct stat stat;
5208
5209 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005210 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005211
5212 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005213 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005216 }
5217
5218 fd = open(args[2], O_RDONLY);
5219 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5220 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5221 file, linenum, args[2], args[1]);
5222 if (fd >= 0)
5223 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005224 err_code |= ERR_ALERT | ERR_FATAL;
5225 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005226 }
5227
Willy Tarreau27a674e2009-08-17 07:23:33 +02005228 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005229 errlen = stat.st_size;
5230 } else {
5231 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005232 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005233 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005234 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005235 }
5236
5237 err = malloc(errlen); /* malloc() must succeed during parsing */
5238 errnum = read(fd, err, errlen);
5239 if (errnum != errlen) {
5240 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5241 file, linenum, args[2], args[1]);
5242 close(fd);
5243 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005246 }
5247 close(fd);
5248
5249 errnum = atol(args[1]);
5250 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5251 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005252 chunk_destroy(&curproxy->errmsg[rc]);
5253 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005254 break;
5255 }
5256 }
5257
5258 if (rc >= HTTP_ERR_SIZE) {
5259 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5260 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005261 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005262 free(err);
5263 }
5264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005266 struct cfg_kw_list *kwl;
5267 int index;
5268
5269 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5270 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5271 if (kwl->kw[index].section != CFG_LISTEN)
5272 continue;
5273 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5274 /* prepare error message just in case */
5275 snprintf(trash, sizeof(trash),
5276 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005277 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5278 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005279 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005282 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005283 else if (rc > 0) {
5284 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005285 err_code |= ERR_WARN;
5286 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005287 }
Willy Tarreau93893792009-07-23 13:19:11 +02005288 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005289 }
5290 }
5291 }
5292
Willy Tarreau6daf3432008-01-22 16:44:08 +01005293 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
Willy Tarreau93893792009-07-23 13:19:11 +02005297 out:
5298 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299}
5300
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005301int
5302cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5303{
5304
5305 int err_code = 0;
5306 const char *err;
5307
5308 if (!strcmp(args[0], "userlist")) { /* new userlist */
5309 struct userlist *newul;
5310
5311 if (!*args[1]) {
5312 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5313 file, linenum, args[0]);
5314 err_code |= ERR_ALERT | ERR_FATAL;
5315 goto out;
5316 }
5317
5318 err = invalid_char(args[1]);
5319 if (err) {
5320 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5321 file, linenum, *err, args[0], args[1]);
5322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
5324 }
5325
5326 for (newul = userlist; newul; newul = newul->next)
5327 if (!strcmp(newul->name, args[1])) {
5328 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5329 file, linenum, args[1]);
5330 err_code |= ERR_WARN;
5331 goto out;
5332 }
5333
5334 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5335 if (!newul) {
5336 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5337 err_code |= ERR_ALERT | ERR_ABORT;
5338 goto out;
5339 }
5340
5341 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5342 newul->name = strdup(args[1]);
5343
5344 if (!newul->groupusers | !newul->name) {
5345 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5346 err_code |= ERR_ALERT | ERR_ABORT;
5347 goto out;
5348 }
5349
5350 newul->next = userlist;
5351 userlist = newul;
5352
5353 } else if (!strcmp(args[0], "group")) { /* new group */
5354 int cur_arg, i;
5355 const char *err;
5356
5357 if (!*args[1]) {
5358 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5359 file, linenum, args[0]);
5360 err_code |= ERR_ALERT | ERR_FATAL;
5361 goto out;
5362 }
5363
5364 err = invalid_char(args[1]);
5365 if (err) {
5366 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5367 file, linenum, *err, args[0], args[1]);
5368 err_code |= ERR_ALERT | ERR_FATAL;
5369 goto out;
5370 }
5371
5372 for(i = 0; i < userlist->grpcnt; i++)
5373 if (!strcmp(userlist->groups[i], args[1])) {
5374 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5375 file, linenum, args[1], userlist->name);
5376 err_code |= ERR_ALERT;
5377 goto out;
5378 }
5379
5380 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5381 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5382 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
5385 }
5386
5387 cur_arg = 2;
5388
5389 while (*args[cur_arg]) {
5390 if (!strcmp(args[cur_arg], "users")) {
5391 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5392 cur_arg += 2;
5393 continue;
5394 } else {
5395 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5396 file, linenum, args[0]);
5397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
5399 }
5400 }
5401
5402 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5403 } else if (!strcmp(args[0], "user")) { /* new user */
5404 struct auth_users *newuser;
5405 int cur_arg;
5406
5407 if (!*args[1]) {
5408 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5409 file, linenum, args[0]);
5410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
5412 }
5413
5414 for (newuser = userlist->users; newuser; newuser = newuser->next)
5415 if (!strcmp(newuser->user, args[1])) {
5416 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5417 file, linenum, args[1], userlist->name);
5418 err_code |= ERR_ALERT;
5419 goto out;
5420 }
5421
5422 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5423 if (!newuser) {
5424 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5425 err_code |= ERR_ALERT | ERR_ABORT;
5426 goto out;
5427 }
5428
5429 newuser->user = strdup(args[1]);
5430
5431 newuser->next = userlist->users;
5432 userlist->users = newuser;
5433
5434 cur_arg = 2;
5435
5436 while (*args[cur_arg]) {
5437 if (!strcmp(args[cur_arg], "password")) {
5438#ifndef CONFIG_HAP_CRYPT
5439 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5440 file, linenum);
5441 err_code |= ERR_ALERT;
5442#endif
5443 newuser->pass = strdup(args[cur_arg + 1]);
5444 cur_arg += 2;
5445 continue;
5446 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5447 newuser->pass = strdup(args[cur_arg + 1]);
5448 newuser->flags |= AU_O_INSECURE;
5449 cur_arg += 2;
5450 continue;
5451 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005452 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005453 cur_arg += 2;
5454 continue;
5455 } else {
5456 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5457 file, linenum, args[0]);
5458 err_code |= ERR_ALERT | ERR_FATAL;
5459 goto out;
5460 }
5461 }
5462 } else {
5463 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 }
5466
5467out:
5468 return err_code;
5469}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470
5471/*
5472 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005473 * Returns the error code, 0 if OK, or any combination of :
5474 * - ERR_ABORT: must abort ASAP
5475 * - ERR_FATAL: we can continue parsing but not start the service
5476 * - ERR_WARN: a warning has been emitted
5477 * - ERR_ALERT: an alert has been emitted
5478 * Only the two first ones can stop processing, the two others are just
5479 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005481int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005483 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 FILE *f;
5485 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005487 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005488
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 if ((f=fopen(file,"r")) == NULL)
5490 return -1;
5491
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005492 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005493 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005494 char *end;
5495 char *args[MAX_LINE_ARGS + 1];
5496 char *line = thisline;
5497
Willy Tarreaubaaee002006-06-26 02:48:02 +02005498 linenum++;
5499
5500 end = line + strlen(line);
5501
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005502 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5503 /* Check if we reached the limit and the last char is not \n.
5504 * Watch out for the last line without the terminating '\n'!
5505 */
5506 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005507 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005508 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005509 }
5510
Willy Tarreaubaaee002006-06-26 02:48:02 +02005511 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005512 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005513 line++;
5514
5515 arg = 0;
5516 args[arg] = line;
5517
5518 while (*line && arg < MAX_LINE_ARGS) {
5519 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5520 * C equivalent value. Other combinations left unchanged (eg: \1).
5521 */
5522 if (*line == '\\') {
5523 int skip = 0;
5524 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5525 *line = line[1];
5526 skip = 1;
5527 }
5528 else if (line[1] == 'r') {
5529 *line = '\r';
5530 skip = 1;
5531 }
5532 else if (line[1] == 'n') {
5533 *line = '\n';
5534 skip = 1;
5535 }
5536 else if (line[1] == 't') {
5537 *line = '\t';
5538 skip = 1;
5539 }
5540 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005541 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005542 unsigned char hex1, hex2;
5543 hex1 = toupper(line[2]) - '0';
5544 hex2 = toupper(line[3]) - '0';
5545 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5546 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5547 *line = (hex1<<4) + hex2;
5548 skip = 3;
5549 }
5550 else {
5551 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005552 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 }
5554 }
5555 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005556 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 end -= skip;
5558 }
5559 line++;
5560 }
5561 else if (*line == '#' || *line == '\n' || *line == '\r') {
5562 /* end of string, end of loop */
5563 *line = 0;
5564 break;
5565 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005566 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005567 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005568 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005569 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005570 line++;
5571 args[++arg] = line;
5572 }
5573 else {
5574 line++;
5575 }
5576 }
5577
5578 /* empty line */
5579 if (!**args)
5580 continue;
5581
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005582 if (*line) {
5583 /* we had to stop due to too many args.
5584 * Let's terminate the string, print the offending part then cut the
5585 * last arg.
5586 */
5587 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5588 line++;
5589 *line = '\0';
5590
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005591 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005592 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005593 err_code |= ERR_ALERT | ERR_FATAL;
5594 args[arg] = line;
5595 }
5596
Willy Tarreau540abe42007-05-02 20:50:16 +02005597 /* zero out remaining args and ensure that at least one entry
5598 * is zeroed out.
5599 */
5600 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 args[arg] = line;
5602 }
5603
Willy Tarreau3842f002009-06-14 11:39:52 +02005604 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005605 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005606 char *tmp;
5607
Willy Tarreau3842f002009-06-14 11:39:52 +02005608 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005609 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005610 for (arg=0; *args[arg+1]; arg++)
5611 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005612 *tmp = '\0'; // fix the next arg to \0
5613 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005614 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005615 else if (!strcmp(args[0], "default")) {
5616 kwm = KWM_DEF;
5617 for (arg=0; *args[arg+1]; arg++)
5618 args[arg] = args[arg+1]; // shift args after inversion
5619 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005620
William Lallemand0f99e342011-10-12 17:50:54 +02005621 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5622 strcmp(args[0], "log") != 0) {
5623 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005624 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005625 }
5626
Willy Tarreau977b8e42006-12-29 14:19:17 +01005627 if (!strcmp(args[0], "listen") ||
5628 !strcmp(args[0], "frontend") ||
5629 !strcmp(args[0], "backend") ||
5630 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005631 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005632 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005633 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005634 cursection = strdup(args[0]);
5635 }
5636 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005637 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005638 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005639 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005640 }
5641 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005642 confsect = CFG_USERLIST;
5643 free(cursection);
5644 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005645 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005646 else if (!strcmp(args[0], "peers")) {
5647 confsect = CFG_PEERS;
5648 free(cursection);
5649 cursection = strdup(args[0]);
5650 }
5651
Willy Tarreaubaaee002006-06-26 02:48:02 +02005652 /* else it's a section keyword */
5653
5654 switch (confsect) {
5655 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005656 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005657 break;
5658 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005659 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005661 case CFG_USERLIST:
5662 err_code |= cfg_parse_users(file, linenum, args, kwm);
5663 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005664 case CFG_PEERS:
5665 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5666 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005667 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005668 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005669 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005671
5672 if (err_code & ERR_ABORT)
5673 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005675 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005676 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005678 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005679}
5680
Willy Tarreaubb925012009-07-23 13:36:36 +02005681/*
5682 * Returns the error code, 0 if OK, or any combination of :
5683 * - ERR_ABORT: must abort ASAP
5684 * - ERR_FATAL: we can continue parsing but not start the service
5685 * - ERR_WARN: a warning has been emitted
5686 * - ERR_ALERT: an alert has been emitted
5687 * Only the two first ones can stop processing, the two others are just
5688 * indicators.
5689 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005690int check_config_validity()
5691{
5692 int cfgerr = 0;
5693 struct proxy *curproxy = NULL;
5694 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005695 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005696 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005697 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698
5699 /*
5700 * Now, check for the integrity of all that we have collected.
5701 */
5702
5703 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005704 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005706 /* first, we will invert the proxy list order */
5707 curproxy = NULL;
5708 while (proxy) {
5709 struct proxy *next;
5710
5711 next = proxy->next;
5712 proxy->next = curproxy;
5713 curproxy = proxy;
5714 if (!next)
5715 break;
5716 proxy = next;
5717 }
5718
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005720 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005721 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005722 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005723 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005724 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005725 unsigned int next_id;
5726
5727 if (!curproxy->uuid) {
5728 /* proxy ID not set, use automatic numbering with first
5729 * spare entry starting with next_pxid.
5730 */
5731 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5732 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5733 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005734 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005735 next_pxid++;
5736
Willy Tarreau55ea7572007-06-17 19:56:27 +02005737
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005739 /* ensure we don't keep listeners uselessly bound */
5740 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741 curproxy = curproxy->next;
5742 continue;
5743 }
5744
Willy Tarreauff01a212009-03-15 13:46:16 +01005745 switch (curproxy->mode) {
5746 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005747 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005748 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005749 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5750 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005751 cfgerr++;
5752 }
5753
5754 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005755 Warning("config : servers will be ignored for %s '%s'.\n",
5756 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005757 break;
5758
5759 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005760 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005761 break;
5762
5763 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005764 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005765 break;
5766 }
5767
5768 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005769 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5770 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 cfgerr++;
5772 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005773
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005774 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005775 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005776 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005777 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5778 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005779 cfgerr++;
5780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005781#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005782 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005783 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5784 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005785 cfgerr++;
5786 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005788 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005789 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5790 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005791 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005792 }
5793 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005794 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005795 /* If no LB algo is set in a backend, and we're not in
5796 * transparent mode, dispatch mode nor proxy mode, we
5797 * want to use balance roundrobin by default.
5798 */
5799 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5800 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801 }
5802 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005803
Willy Tarreau1620ec32011-08-06 17:05:02 +02005804 if (curproxy->options & PR_O_DISPATCH)
5805 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5806 else if (curproxy->options & PR_O_HTTP_PROXY)
5807 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5808 else if (curproxy->options & PR_O_TRANSP)
5809 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005810
Willy Tarreau1620ec32011-08-06 17:05:02 +02005811 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5812 if (curproxy->options & PR_O_DISABLE404) {
5813 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5814 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5815 err_code |= ERR_WARN;
5816 curproxy->options &= ~PR_O_DISABLE404;
5817 }
5818 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5819 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5820 "send-state", proxy_type_str(curproxy), curproxy->id);
5821 err_code |= ERR_WARN;
5822 curproxy->options &= ~PR_O2_CHK_SNDST;
5823 }
Willy Tarreauef781042010-01-27 11:53:01 +01005824 }
5825
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005826 /* if a default backend was specified, let's find it */
5827 if (curproxy->defbe.name) {
5828 struct proxy *target;
5829
Alex Williams96532db2009-11-01 21:27:13 -05005830 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005831 if (!target) {
5832 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5833 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005834 cfgerr++;
5835 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005836 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5837 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005838 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005839 } else {
5840 free(curproxy->defbe.name);
5841 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005842 /* we force the backend to be present on at least all of
5843 * the frontend's processes.
5844 */
5845 target->bind_proc = curproxy->bind_proc ?
5846 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005847
5848 /* Emit a warning if this proxy also has some servers */
5849 if (curproxy->srv) {
5850 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5851 curproxy->id);
5852 err_code |= ERR_WARN;
5853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005854 }
5855 }
5856
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005857 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005858 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5859 /* map jump target for ACT_SETBE in req_rep chain */
5860 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005861 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005862 struct proxy *target;
5863
Willy Tarreaua496b602006-12-17 23:15:24 +01005864 if (exp->action != ACT_SETBE)
5865 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005866
Alex Williams96532db2009-11-01 21:27:13 -05005867 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005868 if (!target) {
5869 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5870 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005871 cfgerr++;
5872 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005873 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5874 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005875 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005876 } else {
5877 free((void *)exp->replace);
5878 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005879 /* we force the backend to be present on at least all of
5880 * the frontend's processes.
5881 */
5882 target->bind_proc = curproxy->bind_proc ?
5883 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005884 }
5885 }
5886 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005887
5888 /* find the target proxy for 'use_backend' rules */
5889 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005890 struct proxy *target;
5891
Alex Williams96532db2009-11-01 21:27:13 -05005892 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005893
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005894 if (!target) {
5895 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5896 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005897 cfgerr++;
5898 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005899 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5900 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005901 cfgerr++;
5902 } else {
5903 free((void *)rule->be.name);
5904 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005905 /* we force the backend to be present on at least all of
5906 * the frontend's processes.
5907 */
5908 target->bind_proc = curproxy->bind_proc ?
5909 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005910 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005911 }
5912
5913 /* find the target proxy for 'use_backend' rules */
5914 list_for_each_entry(srule, &curproxy->server_rules, list) {
5915 struct server *target = findserver(curproxy, srule->srv.name);
5916
5917 if (!target) {
5918 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5919 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5920 cfgerr++;
5921 continue;
5922 }
5923 free((void *)srule->srv.name);
5924 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005925 }
5926
Emeric Brunb982a3d2010-01-04 15:45:53 +01005927 /* find the target table for 'stick' rules */
5928 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5929 struct proxy *target;
5930
Emeric Brun1d33b292010-01-04 15:47:17 +01005931 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5932 if (mrule->flags & STK_IS_STORE)
5933 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5934
Emeric Brunb982a3d2010-01-04 15:45:53 +01005935 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005936 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005937 else
5938 target = curproxy;
5939
5940 if (!target) {
5941 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5942 curproxy->id, mrule->table.name);
5943 cfgerr++;
5944 }
5945 else if (target->table.size == 0) {
5946 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5947 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5948 cfgerr++;
5949 }
Willy Tarreau12785782012-04-27 21:37:17 +02005950 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5951 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005952 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5953 cfgerr++;
5954 }
5955 else {
5956 free((void *)mrule->table.name);
5957 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005958 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005959 }
5960 }
5961
5962 /* find the target table for 'store response' rules */
5963 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5964 struct proxy *target;
5965
Emeric Brun1d33b292010-01-04 15:47:17 +01005966 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5967
Emeric Brunb982a3d2010-01-04 15:45:53 +01005968 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005969 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005970 else
5971 target = curproxy;
5972
5973 if (!target) {
5974 Alert("Proxy '%s': unable to find store table '%s'.\n",
5975 curproxy->id, mrule->table.name);
5976 cfgerr++;
5977 }
5978 else if (target->table.size == 0) {
5979 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5980 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5981 cfgerr++;
5982 }
Willy Tarreau12785782012-04-27 21:37:17 +02005983 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5984 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005985 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5986 cfgerr++;
5987 }
5988 else {
5989 free((void *)mrule->table.name);
5990 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005991 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005992 }
5993 }
5994
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005995 /* find the target table for 'tcp-request' layer 4 rules */
5996 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5997 struct proxy *target;
5998
Willy Tarreau56123282010-08-06 19:06:56 +02005999 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006000 continue;
6001
6002 if (trule->act_prm.trk_ctr.table.n)
6003 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6004 else
6005 target = curproxy;
6006
6007 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006008 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6009 curproxy->id, trule->act_prm.trk_ctr.table.n,
6010 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006011 cfgerr++;
6012 }
6013 else if (target->table.size == 0) {
6014 Alert("Proxy '%s': table '%s' used but not configured.\n",
6015 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6016 cfgerr++;
6017 }
6018 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006019 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 +02006020 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6021 cfgerr++;
6022 }
6023 else {
6024 free(trule->act_prm.trk_ctr.table.n);
6025 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006026 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006027 * to pass a list of counters to track and allocate them right here using
6028 * stktable_alloc_data_type().
6029 */
6030 }
6031 }
6032
Willy Tarreaud1f96522010-08-03 19:34:32 +02006033 /* find the target table for 'tcp-request' layer 6 rules */
6034 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6035 struct proxy *target;
6036
Willy Tarreau56123282010-08-06 19:06:56 +02006037 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006038 continue;
6039
6040 if (trule->act_prm.trk_ctr.table.n)
6041 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6042 else
6043 target = curproxy;
6044
6045 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006046 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6047 curproxy->id, trule->act_prm.trk_ctr.table.n,
6048 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006049 cfgerr++;
6050 }
6051 else if (target->table.size == 0) {
6052 Alert("Proxy '%s': table '%s' used but not configured.\n",
6053 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6054 cfgerr++;
6055 }
6056 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006057 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 +02006058 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6059 cfgerr++;
6060 }
6061 else {
6062 free(trule->act_prm.trk_ctr.table.n);
6063 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006064 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006065 * to pass a list of counters to track and allocate them right here using
6066 * stktable_alloc_data_type().
6067 */
6068 }
6069 }
6070
Emeric Brun32da3c42010-09-23 18:39:19 +02006071 if (curproxy->table.peers.name) {
6072 struct peers *curpeers = peers;
6073
6074 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6075 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6076 free((void *)curproxy->table.peers.name);
6077 curproxy->table.peers.p = peers;
6078 break;
6079 }
6080 }
6081
6082 if (!curpeers) {
6083 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6084 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006085 free((void *)curproxy->table.peers.name);
6086 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006087 cfgerr++;
6088 }
6089 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006090 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6091 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006092 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006093 cfgerr++;
6094 }
6095 }
6096
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006097 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006098 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006099 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6100 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6101 "proxy", curproxy->id);
6102 cfgerr++;
6103 goto out_uri_auth_compat;
6104 }
6105
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006106 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006107 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006108 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006109 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006110
Willy Tarreau95fa4692010-02-01 13:05:50 +01006111 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6112 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006113
6114 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006115 uri_auth_compat_req[i++] = "realm";
6116 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6117 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006118
Willy Tarreau95fa4692010-02-01 13:05:50 +01006119 uri_auth_compat_req[i++] = "unless";
6120 uri_auth_compat_req[i++] = "{";
6121 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6122 uri_auth_compat_req[i++] = "}";
6123 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006124
Willy Tarreauff011f22011-01-06 17:51:27 +01006125 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6126 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006127 cfgerr++;
6128 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006129 }
6130
Willy Tarreauff011f22011-01-06 17:51:27 +01006131 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006132
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006133 if (curproxy->uri_auth->auth_realm) {
6134 free(curproxy->uri_auth->auth_realm);
6135 curproxy->uri_auth->auth_realm = NULL;
6136 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006137
6138 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006139 }
6140out_uri_auth_compat:
6141
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006142 cfgerr += acl_find_targets(curproxy);
6143
Willy Tarreau2738a142006-07-08 17:28:09 +02006144 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006145 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006146 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006147 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006148 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006149 " | While not properly invalid, you will certainly encounter various problems\n"
6150 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006151 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006152 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006153 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006154 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006155
Willy Tarreau1fa31262007-12-03 00:36:16 +01006156 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6157 * We must still support older configurations, so let's find out whether those
6158 * parameters have been set or must be copied from contimeouts.
6159 */
6160 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006161 if (!curproxy->timeout.tarpit ||
6162 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006163 /* tarpit timeout not set. We search in the following order:
6164 * default.tarpit, curr.connect, default.connect.
6165 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006166 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006167 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006168 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006169 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006170 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006171 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006172 }
6173 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006174 (!curproxy->timeout.queue ||
6175 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006176 /* queue timeout not set. We search in the following order:
6177 * default.queue, curr.connect, default.connect.
6178 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006179 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006180 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006181 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006182 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006183 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006184 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006185 }
6186 }
6187
Willy Tarreau1620ec32011-08-06 17:05:02 +02006188 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006189 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6190 curproxy->check_req = (char *)malloc(curproxy->check_len);
6191 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006192 }
6193
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006194 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006195 if (curproxy->nb_req_cap) {
6196 if (curproxy->mode == PR_MODE_HTTP) {
6197 curproxy->req_cap_pool = create_pool("ptrcap",
6198 curproxy->nb_req_cap * sizeof(char *),
6199 MEM_F_SHARED);
6200 } else {
6201 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6202 proxy_type_str(curproxy), curproxy->id);
6203 err_code |= ERR_WARN;
6204 curproxy->to_log &= ~LW_REQHDR;
6205 curproxy->nb_req_cap = 0;
6206 }
6207 }
6208
6209 if (curproxy->nb_rsp_cap) {
6210 if (curproxy->mode == PR_MODE_HTTP) {
6211 curproxy->rsp_cap_pool = create_pool("ptrcap",
6212 curproxy->nb_rsp_cap * sizeof(char *),
6213 MEM_F_SHARED);
6214 } else {
6215 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6216 proxy_type_str(curproxy), curproxy->id);
6217 err_code |= ERR_WARN;
6218 curproxy->to_log &= ~LW_REQHDR;
6219 curproxy->nb_rsp_cap = 0;
6220 }
6221 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006222
Willy Tarreaubaaee002006-06-26 02:48:02 +02006223 /* first, we will invert the servers list order */
6224 newsrv = NULL;
6225 while (curproxy->srv) {
6226 struct server *next;
6227
6228 next = curproxy->srv->next;
6229 curproxy->srv->next = newsrv;
6230 newsrv = curproxy->srv;
6231 if (!next)
6232 break;
6233 curproxy->srv = next;
6234 }
6235
Willy Tarreaudd701652010-05-25 23:03:02 +02006236 /* assign automatic UIDs to servers which don't have one yet */
6237 next_id = 1;
6238 newsrv = curproxy->srv;
6239 while (newsrv != NULL) {
6240 if (!newsrv->puid) {
6241 /* server ID not set, use automatic numbering with first
6242 * spare entry starting with next_svid.
6243 */
6244 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6245 newsrv->conf.id.key = newsrv->puid = next_id;
6246 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6247 }
6248 next_id++;
6249 newsrv = newsrv->next;
6250 }
6251
Willy Tarreau20697042007-11-15 23:26:18 +01006252 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006253 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006254
Willy Tarreau62c3be22012-01-20 13:12:32 +01006255 /*
6256 * If this server supports a maxconn parameter, it needs a dedicated
6257 * tasks to fill the emptied slots when a connection leaves.
6258 * Also, resolve deferred tracking dependency if needed.
6259 */
6260 newsrv = curproxy->srv;
6261 while (newsrv != NULL) {
6262 if (newsrv->minconn > newsrv->maxconn) {
6263 /* Only 'minconn' was specified, or it was higher than or equal
6264 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6265 * this will avoid further useless expensive computations.
6266 */
6267 newsrv->maxconn = newsrv->minconn;
6268 } else if (newsrv->maxconn && !newsrv->minconn) {
6269 /* minconn was not specified, so we set it to maxconn */
6270 newsrv->minconn = newsrv->maxconn;
6271 }
6272
6273 if (newsrv->trackit) {
6274 struct proxy *px;
6275 struct server *srv;
6276 char *pname, *sname;
6277
6278 pname = newsrv->trackit;
6279 sname = strrchr(pname, '/');
6280
6281 if (sname)
6282 *sname++ = '\0';
6283 else {
6284 sname = pname;
6285 pname = NULL;
6286 }
6287
6288 if (pname) {
6289 px = findproxy(pname, PR_CAP_BE);
6290 if (!px) {
6291 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6292 proxy_type_str(curproxy), curproxy->id,
6293 newsrv->id, pname);
6294 cfgerr++;
6295 goto next_srv;
6296 }
6297 } else
6298 px = curproxy;
6299
6300 srv = findserver(px, sname);
6301 if (!srv) {
6302 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6303 proxy_type_str(curproxy), curproxy->id,
6304 newsrv->id, sname);
6305 cfgerr++;
6306 goto next_srv;
6307 }
6308
6309 if (!(srv->state & SRV_CHECKED)) {
6310 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6311 "tracking as it does not have checks enabled.\n",
6312 proxy_type_str(curproxy), curproxy->id,
6313 newsrv->id, px->id, srv->id);
6314 cfgerr++;
6315 goto next_srv;
6316 }
6317
6318 if (curproxy != px &&
6319 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6320 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6321 "tracking: disable-on-404 option inconsistency.\n",
6322 proxy_type_str(curproxy), curproxy->id,
6323 newsrv->id, px->id, srv->id);
6324 cfgerr++;
6325 goto next_srv;
6326 }
6327
6328 /* if the other server is forced disabled, we have to do the same here */
6329 if (srv->state & SRV_MAINTAIN) {
6330 newsrv->state |= SRV_MAINTAIN;
6331 newsrv->state &= ~SRV_RUNNING;
6332 newsrv->health = 0;
6333 }
6334
6335 newsrv->track = srv;
6336 newsrv->tracknext = srv->tracknext;
6337 srv->tracknext = newsrv;
6338
6339 free(newsrv->trackit);
6340 newsrv->trackit = NULL;
6341 }
6342 next_srv:
6343 newsrv = newsrv->next;
6344 }
6345
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006346 /* We have to initialize the server lookup mechanism depending
6347 * on what LB algorithm was choosen.
6348 */
6349
6350 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6351 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6352 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006353 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6354 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6355 init_server_map(curproxy);
6356 } else {
6357 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6358 fwrr_init_server_groups(curproxy);
6359 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006360 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006361
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006362 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006363 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6364 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6365 fwlc_init_server_tree(curproxy);
6366 } else {
6367 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6368 fas_init_server_tree(curproxy);
6369 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006370 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006371
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006372 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006373 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6374 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6375 chash_init_server_tree(curproxy);
6376 } else {
6377 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6378 init_server_map(curproxy);
6379 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006380 break;
6381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006382
6383 if (curproxy->options & PR_O_LOGASAP)
6384 curproxy->to_log &= ~LW_BYTES;
6385
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006386 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006387 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006388 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6389 proxy_type_str(curproxy), curproxy->id);
6390 err_code |= ERR_WARN;
6391 }
6392
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006393 if (curproxy->mode != PR_MODE_HTTP) {
6394 int optnum;
6395
6396 if (curproxy->options & PR_O_COOK_ANY) {
6397 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6398 proxy_type_str(curproxy), curproxy->id);
6399 err_code |= ERR_WARN;
6400 }
6401
6402 if (curproxy->uri_auth) {
6403 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6404 proxy_type_str(curproxy), curproxy->id);
6405 err_code |= ERR_WARN;
6406 curproxy->uri_auth = NULL;
6407 }
6408
Willy Tarreau87cf5142011-08-19 22:57:24 +02006409 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006410 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6411 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6412 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006413 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006414 }
6415
6416 if (curproxy->options & PR_O_ORGTO) {
6417 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6418 "originalto", proxy_type_str(curproxy), curproxy->id);
6419 err_code |= ERR_WARN;
6420 curproxy->options &= ~PR_O_ORGTO;
6421 }
6422
6423 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6424 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6425 (curproxy->cap & cfg_opts[optnum].cap) &&
6426 (curproxy->options & cfg_opts[optnum].val)) {
6427 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6428 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6429 err_code |= ERR_WARN;
6430 curproxy->options &= ~cfg_opts[optnum].val;
6431 }
6432 }
6433
6434 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6435 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6436 (curproxy->cap & cfg_opts2[optnum].cap) &&
6437 (curproxy->options2 & cfg_opts2[optnum].val)) {
6438 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6439 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6440 err_code |= ERR_WARN;
6441 curproxy->options2 &= ~cfg_opts2[optnum].val;
6442 }
6443 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006444
Willy Tarreauefa5f512010-03-30 20:13:29 +02006445#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006446 if (curproxy->bind_hdr_occ) {
6447 curproxy->bind_hdr_occ = 0;
6448 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6449 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6450 err_code |= ERR_WARN;
6451 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006452#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006453 }
6454
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006456 * ensure that we're not cross-dressing a TCP server into HTTP.
6457 */
6458 newsrv = curproxy->srv;
6459 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006460 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006461 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6462 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006463 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006464 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006465
Willy Tarreau0cec3312011-10-31 13:49:26 +01006466 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6467 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6468 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6469 err_code |= ERR_WARN;
6470 }
6471
Willy Tarreauefa5f512010-03-30 20:13:29 +02006472#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006473 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6474 newsrv->bind_hdr_occ = 0;
6475 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6476 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6477 err_code |= ERR_WARN;
6478 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006479#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006480 newsrv = newsrv->next;
6481 }
6482
Willy Tarreauc1a21672009-08-16 22:37:44 +02006483 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006484 curproxy->accept = frontend_accept;
6485
Willy Tarreauc1a21672009-08-16 22:37:44 +02006486 if (curproxy->tcp_req.inspect_delay ||
6487 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006488 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006489
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006490 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006491 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006492 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006493 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006494
6495 /* both TCP and HTTP must check switching rules */
6496 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6497 }
6498
6499 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006500 if (curproxy->tcp_req.inspect_delay ||
6501 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6502 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6503
Emeric Brun97679e72010-09-23 17:56:44 +02006504 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6505 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6506
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006507 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006508 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006509 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006510 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006511
6512 /* If the backend does requires RDP cookie persistence, we have to
6513 * enable the corresponding analyser.
6514 */
6515 if (curproxy->options2 & PR_O2_RDPC_PRST)
6516 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6517 }
6518
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006519 listener = NULL;
6520 while (curproxy->listen) {
6521 struct listener *next;
6522
6523 next = curproxy->listen->next;
6524 curproxy->listen->next = listener;
6525 listener = curproxy->listen;
6526
6527 if (!next)
6528 break;
6529
6530 curproxy->listen = next;
6531 }
6532
Willy Tarreaue6b98942007-10-29 01:09:36 +01006533 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006534 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006535 listener = curproxy->listen;
6536 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006537 if (!listener->luid) {
6538 /* listener ID not set, use automatic numbering with first
6539 * spare entry starting with next_luid.
6540 */
6541 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6542 listener->conf.id.key = listener->luid = next_id;
6543 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006544 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006545 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006546
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006547 /* enable separate counters */
6548 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6549 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6550 if (!listener->name) {
6551 sprintf(trash, "sock-%d", listener->luid);
6552 listener->name = strdup(trash);
6553 }
6554 }
6555
Willy Tarreaue6b98942007-10-29 01:09:36 +01006556 if (curproxy->options & PR_O_TCP_NOLING)
6557 listener->options |= LI_O_NOLINGER;
6558 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006559 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006560 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006561 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006562 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006563 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006564 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006565
Willy Tarreau8a956912010-10-15 14:27:08 +02006566 if (listener->options & LI_O_ACC_PROXY)
6567 listener->analysers |= AN_REQ_DECODE_PROXY;
6568
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006569 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6570 listener->options |= LI_O_TCP_RULES;
6571
Willy Tarreaude3041d2010-05-31 10:56:17 +02006572 if (curproxy->mon_mask.s_addr)
6573 listener->options |= LI_O_CHK_MONNET;
6574
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006575 /* smart accept mode is automatic in HTTP mode */
6576 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6577 (curproxy->mode == PR_MODE_HTTP &&
6578 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6579 listener->options |= LI_O_NOQUICKACK;
6580
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006581 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006582 listener = listener->next;
6583 }
6584
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006585 /* Check multi-process mode compatibility for the current proxy */
6586 if (global.nbproc > 1) {
6587 int nbproc = 0;
6588 if (curproxy->bind_proc) {
6589 int proc;
6590 for (proc = 0; proc < global.nbproc; proc++) {
6591 if (curproxy->bind_proc & (1 << proc)) {
6592 nbproc++;
6593 }
6594 }
6595 } else {
6596 nbproc = global.nbproc;
6597 }
6598 if (curproxy->table.peers.name) {
6599 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6600 curproxy->id);
6601 cfgerr++;
6602 }
6603 if (nbproc > 1) {
6604 if (curproxy->uri_auth) {
6605 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6606 curproxy->id);
6607 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6608 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6609 curproxy->id);
6610 }
6611 }
6612 if (curproxy->appsession_name) {
6613 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6614 curproxy->id);
6615 }
6616 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6617 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6618 curproxy->id);
6619 }
6620 }
6621 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006622
6623 /* create the task associated with the proxy */
6624 curproxy->task = task_new();
6625 if (curproxy->task) {
6626 curproxy->task->context = curproxy;
6627 curproxy->task->process = manage_proxy;
6628 /* no need to queue, it will be done automatically if some
6629 * listener gets limited.
6630 */
6631 curproxy->task->expire = TICK_ETERNITY;
6632 } else {
6633 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6634 curproxy->id);
6635 cfgerr++;
6636 }
6637
Willy Tarreaubaaee002006-06-26 02:48:02 +02006638 curproxy = curproxy->next;
6639 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006640
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006641 /* Check multi-process mode compatibility */
6642 if (global.nbproc > 1) {
6643 if (global.stats_fe) {
6644 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6645 }
6646 }
6647
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006648 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6649 struct auth_users *curuser;
6650 int g;
6651
6652 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6653 unsigned int group_mask = 0;
6654 char *group = NULL;
6655
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006656 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006657 continue;
6658
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006659 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006660
6661 for (g = 0; g < curuserlist->grpcnt; g++)
6662 if (!strcmp(curuserlist->groups[g], group))
6663 break;
6664
6665 if (g == curuserlist->grpcnt) {
6666 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6667 curuserlist->name, group, curuser->user);
6668 err_code |= ERR_ALERT | ERR_FATAL;
6669 goto out;
6670 }
6671
6672 group_mask |= (1 << g);
6673 }
6674
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006675 free(curuser->u.groups);
6676 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006677 }
6678
6679 for (g = 0; g < curuserlist->grpcnt; g++) {
6680 char *user = NULL;
6681
6682 if (!curuserlist->groupusers[g])
6683 continue;
6684
6685 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6686 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6687 if (!strcmp(curuser->user, user))
6688 break;
6689
6690 if (!curuser) {
6691 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6692 curuserlist->name, user, curuserlist->groups[g]);
6693 err_code |= ERR_ALERT | ERR_FATAL;
6694 goto out;
6695 }
6696
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006697 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006698 }
6699
6700 free(curuserlist->groupusers[g]);
6701 }
6702
6703 free(curuserlist->groupusers);
6704
6705#ifdef DEBUG_AUTH
6706 for (g = 0; g < curuserlist->grpcnt; g++) {
6707 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6708
6709 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6710 if (curuser->group_mask & (1 << g))
6711 fprintf(stderr, " %s", curuser->user);
6712 }
6713
6714 fprintf(stderr, "\n");
6715 }
6716#endif
6717
Willy Tarreaufbb78422011-06-05 15:38:35 +02006718 }
6719
6720 /* automatically compute fullconn if not set. We must not do it in the
6721 * loop above because cross-references are not yet fully resolved.
6722 */
6723 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6724 /* If <fullconn> is not set, let's set it to 10% of the sum of
6725 * the possible incoming frontend's maxconns.
6726 */
6727 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6728 struct proxy *fe;
6729 int total = 0;
6730
6731 /* sum up the number of maxconns of frontends which
6732 * reference this backend at least once or which are
6733 * the same one ('listen').
6734 */
6735 for (fe = proxy; fe; fe = fe->next) {
6736 struct switching_rule *rule;
6737 struct hdr_exp *exp;
6738 int found = 0;
6739
6740 if (!(fe->cap & PR_CAP_FE))
6741 continue;
6742
6743 if (fe == curproxy) /* we're on a "listen" instance */
6744 found = 1;
6745
6746 if (fe->defbe.be == curproxy) /* "default_backend" */
6747 found = 1;
6748
6749 /* check if a "use_backend" rule matches */
6750 if (!found) {
6751 list_for_each_entry(rule, &fe->switching_rules, list) {
6752 if (rule->be.backend == curproxy) {
6753 found = 1;
6754 break;
6755 }
6756 }
6757 }
6758
6759 /* check if a "reqsetbe" rule matches */
6760 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6761 if (exp->action == ACT_SETBE &&
6762 (struct proxy *)exp->replace == curproxy) {
6763 found = 1;
6764 break;
6765 }
6766 }
6767
6768 /* now we've checked all possible ways to reference a backend
6769 * from a frontend.
6770 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006771 if (!found)
6772 continue;
6773 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006774 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006775 /* we have the sum of the maxconns in <total>. We only
6776 * keep 10% of that sum to set the default fullconn, with
6777 * a hard minimum of 1 (to avoid a divide by zero).
6778 */
6779 curproxy->fullconn = (total + 9) / 10;
6780 if (!curproxy->fullconn)
6781 curproxy->fullconn = 1;
6782 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006783 }
6784
Willy Tarreau056f5682010-06-06 15:51:11 +02006785 /* initialize stick-tables on backend capable proxies. This must not
6786 * be done earlier because the data size may be discovered while parsing
6787 * other proxies.
6788 */
6789 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006790 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006791
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006792 /*
6793 * Recount currently required checks.
6794 */
6795
6796 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6797 int optnum;
6798
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006799 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6800 if (curproxy->options & cfg_opts[optnum].val)
6801 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006802
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006803 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6804 if (curproxy->options2 & cfg_opts2[optnum].val)
6805 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006806 }
6807
Willy Tarreau122541c2011-09-07 21:24:49 +02006808 if (peers) {
6809 struct peers *curpeers = peers, **last;
6810 struct peer *p, *pb;
6811
6812 /* Remove all peers sections which don't have a valid listener.
6813 * This can happen when a peers section is never referenced and
6814 * does not contain a local peer.
6815 */
6816 last = &peers;
6817 while (*last) {
6818 curpeers = *last;
6819 if (curpeers->peers_fe) {
6820 last = &curpeers->next;
6821 continue;
6822 }
6823
6824 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6825 curpeers->id, localpeer);
6826
6827 p = curpeers->remote;
6828 while (p) {
6829 pb = p->next;
6830 free(p->id);
6831 free(p);
6832 p = pb;
6833 }
6834
6835 /* Destroy and unlink this curpeers section.
6836 * Note: curpeers is backed up into *last.
6837 */
6838 free(curpeers->id);
6839 curpeers = curpeers->next;
6840 free(*last);
6841 *last = curpeers;
6842 }
6843 }
6844
Willy Tarreauac1932d2011-10-24 19:14:41 +02006845 if (!global.tune.max_http_hdr)
6846 global.tune.max_http_hdr = MAX_HTTP_HDR;
6847
Willy Tarreau34eb6712011-10-24 18:15:04 +02006848 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006849 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006850 MEM_F_SHARED);
6851
Willy Tarreaubb925012009-07-23 13:36:36 +02006852 if (cfgerr > 0)
6853 err_code |= ERR_ALERT | ERR_FATAL;
6854 out:
6855 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006856}
6857
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006858/*
6859 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6860 * parsing sessions.
6861 */
6862void cfg_register_keywords(struct cfg_kw_list *kwl)
6863{
6864 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6865}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006866
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006867/*
6868 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6869 */
6870void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6871{
6872 LIST_DEL(&kwl->list);
6873 LIST_INIT(&kwl->list);
6874}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006875
6876/*
6877 * Local variables:
6878 * c-indent-level: 8
6879 * c-basic-offset: 8
6880 * End:
6881 */