blob: 00531e594fcecfe9f78928aa901f48310597d913 [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>
Willy Tarreauc7e42382012-08-24 19:22:53 +020029#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020031#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020032#include <common/memory.h>
33#include <common/standard.h>
34#include <common/time.h>
35#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
37#include <types/capture.h>
38#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020046#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020047#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020048#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020049#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010050#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020051#include <proto/lb_fwlc.h>
52#include <proto/lb_fwrr.h>
53#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020055#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/protocols.h>
57#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020058#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010060#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020061#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020062#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010064#include <proto/session.h>
Emeric Brunaa35f1f2012-09-03 11:53:36 +020065#include <proto/shctx.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Emeric Brun6e159292012-05-18 16:32:13 +020067#ifdef USE_OPENSSL
68#include <proto/ssl_sock.h>
69#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020070#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010071#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072
73
Willy Tarreauf3c69202006-07-09 16:42:34 +020074/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
75 * ssl-hello-chk option to ensure that the remote server speaks SSL.
76 *
77 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
78 */
79const char sslv3_client_hello_pkt[] = {
80 "\x16" /* ContentType : 0x16 = Hanshake */
81 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
82 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
83 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
84 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
85 "\x03\x00" /* Hello Version : 0x0300 = v3 */
86 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
87 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
88 "\x00" /* Session ID length : empty (no session ID) */
89 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
90 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
91 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
92 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
93 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
94 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
95 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
96 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
97 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
98 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
99 "\x00\x38" "\x00\x39" "\x00\x3A"
100 "\x01" /* Compression Length : 0x01 = 1 byte for types */
101 "\x00" /* Compression Type : 0x00 = NULL compression */
102};
103
Willy Tarreau3842f002009-06-14 11:39:52 +0200104/* various keyword modifiers */
105enum kw_mod {
106 KWM_STD = 0, /* normal */
107 KWM_NO, /* "no" prefixed before the keyword */
108 KWM_DEF, /* "default" prefixed before the keyword */
109};
110
Willy Tarreau13943ab2006-12-31 00:24:10 +0100111/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113 const char *name;
114 unsigned int val;
115 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100116 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118};
119
120/* proxy->options */
121static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100122{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100123 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
124 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
125 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
127 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
128 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
129 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
130 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
131 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
133 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100195static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196{
197 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100198 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 int port, end;
200
201 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200202
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 while (next && *next) {
204 struct sockaddr_storage ss;
205
206 str = next;
207 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100208 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209 *next++ = 0;
210 }
211
Emeric Bruned760922010-10-22 17:59:25 +0200212 if (*str == '/') {
213 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
214 /* so compute max path */
215 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
216 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 +0200217
Emeric Bruned760922010-10-22 17:59:25 +0200218 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100219 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
220 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200221 goto fail;
222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200225 ss.ss_family = AF_UNIX;
226 if (global.unix_bind.prefix) {
227 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
228 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 }
Emeric Bruned760922010-10-22 17:59:25 +0200230 else {
231 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
232 }
233 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 }
235 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100238 ss2 = str2sa_range(str, &port, &end);
239 if (!ss2) {
240 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
241 file, line, str);
242 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 if (!port) {
246 Alert("parsing [%s:%d] : missing port number: '%s'\n",
247 file, line, str);
248 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100251 /* OK the address looks correct */
252 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253
Emeric Bruned760922010-10-22 17:59:25 +0200254 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100255 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
256 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
259
260 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100261 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
262 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
266
267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269 l->next = curproxy->listen;
270 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271
272 l->fd = -1;
273 l->addr = ss;
Willy Tarreauc5788912012-08-24 18:12:41 +0200274 l->data = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100275 l->state = LI_INIT;
276
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100277 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100279 tcpv4_add_listener(l);
280 }
Emeric Bruned760922010-10-22 17:59:25 +0200281 else if (ss.ss_family == AF_INET6) {
282 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
283 tcpv6_add_listener(l);
284 }
285 else {
286 l->perm.ux.gid = l->perm.ux.uid = -1;
287 l->perm.ux.mode = 0;
288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 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 reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100417/* Report it if a request ACL condition uses some response-only parameters. It
418 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
419 * Note that <cond> may be NULL and then will be ignored.
420 */
421static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
422{
423 struct acl *acl;
424
425 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
426 return 0;
427
428 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
429 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
430 file, line, acl ? acl->name : "(unknown)");
431 return ERR_WARN;
432}
433
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100434/* Report it if a request ACL condition uses some request-only volatile parameters.
435 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
436 * Note that <cond> may be NULL and then will be ignored.
437 */
438static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
439{
440 struct acl *acl;
441
442 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
443 return 0;
444
445 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
446 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
447 file, line, acl ? acl->name : "(unknown)");
448 return ERR_WARN;
449}
450
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
471 else if (!strcmp(args[0], "daemon")) {
472 global.mode |= MODE_DAEMON;
473 }
474 else if (!strcmp(args[0], "debug")) {
475 global.mode |= MODE_DEBUG;
476 }
477 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200480 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100481 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200482 }
483 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100484 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100487 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100489 else if (!strcmp(args[0], "nosplice")) {
490 global.tune.options &= ~GTUNE_USE_SPLICE;
491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492 else if (!strcmp(args[0], "quiet")) {
493 global.mode |= MODE_QUIET;
494 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200495 else if (!strcmp(args[0], "tune.maxpollevents")) {
496 if (global.tune.maxpollevents != 0) {
497 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 err_code |= ERR_ALERT;
499 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200500 }
501 if (*(args[1]) == 0) {
502 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200503 err_code |= ERR_ALERT | ERR_FATAL;
504 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200505 }
506 global.tune.maxpollevents = atol(args[1]);
507 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100508 else if (!strcmp(args[0], "tune.maxaccept")) {
509 if (global.tune.maxaccept != 0) {
510 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200511 err_code |= ERR_ALERT;
512 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100513 }
514 if (*(args[1]) == 0) {
515 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200516 err_code |= ERR_ALERT | ERR_FATAL;
517 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100518 }
519 global.tune.maxaccept = atol(args[1]);
520 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200521 else if (!strcmp(args[0], "tune.chksize")) {
522 if (*(args[1]) == 0) {
523 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
524 err_code |= ERR_ALERT | ERR_FATAL;
525 goto out;
526 }
527 global.tune.chksize = atol(args[1]);
528 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200529#ifdef USE_OPENSSL
530 else if (!strcmp(args[0], "tune.sslcachesize")) {
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.sslcachesize = atol(args[1]);
537 }
538#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200539 else if (!strcmp(args[0], "tune.bufsize")) {
540 if (*(args[1]) == 0) {
541 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
542 err_code |= ERR_ALERT | ERR_FATAL;
543 goto out;
544 }
545 global.tune.bufsize = atol(args[1]);
546 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
547 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200548 trashlen = global.tune.bufsize;
549 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200550 }
551 else if (!strcmp(args[0], "tune.maxrewrite")) {
552 if (*(args[1]) == 0) {
553 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT | ERR_FATAL;
555 goto out;
556 }
557 global.tune.maxrewrite = atol(args[1]);
558 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
559 global.tune.maxrewrite = global.tune.bufsize / 2;
560 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100561 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
562 if (global.tune.client_rcvbuf != 0) {
563 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT;
565 goto out;
566 }
567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.client_rcvbuf = atol(args[1]);
573 }
574 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
575 if (global.tune.server_rcvbuf != 0) {
576 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT;
578 goto out;
579 }
580 if (*(args[1]) == 0) {
581 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT | ERR_FATAL;
583 goto out;
584 }
585 global.tune.server_rcvbuf = atol(args[1]);
586 }
587 else if (!strcmp(args[0], "tune.sndbuf.client")) {
588 if (global.tune.client_sndbuf != 0) {
589 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
590 err_code |= ERR_ALERT;
591 goto out;
592 }
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.client_sndbuf = atol(args[1]);
599 }
600 else if (!strcmp(args[0], "tune.sndbuf.server")) {
601 if (global.tune.server_sndbuf != 0) {
602 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT;
604 goto out;
605 }
606 if (*(args[1]) == 0) {
607 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT | ERR_FATAL;
609 goto out;
610 }
611 global.tune.server_sndbuf = atol(args[1]);
612 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200613 else if (!strcmp(args[0], "tune.pipesize")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.pipesize = atol(args[1]);
620 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200621 else if (!strcmp(args[0], "tune.http.maxhdr")) {
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.tune.max_http_hdr = atol(args[1]);
628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "uid")) {
630 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200631 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.uid = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "gid")) {
643 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.gid = atol(args[1]);
654 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200655 /* user/group name handling */
656 else if (!strcmp(args[0], "user")) {
657 struct passwd *ha_user;
658 if (global.uid != 0) {
659 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT;
661 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200662 }
663 errno = 0;
664 ha_user = getpwnam(args[1]);
665 if (ha_user != NULL) {
666 global.uid = (int)ha_user->pw_uid;
667 }
668 else {
669 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 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200671 }
672 }
673 else if (!strcmp(args[0], "group")) {
674 struct group *ha_group;
675 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200676 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200679 }
680 errno = 0;
681 ha_group = getgrnam(args[1]);
682 if (ha_group != NULL) {
683 global.gid = (int)ha_group->gr_gid;
684 }
685 else {
686 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 +0200687 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200688 }
689 }
690 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200691 else if (!strcmp(args[0], "nbproc")) {
692 if (global.nbproc != 0) {
693 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200694 err_code |= ERR_ALERT;
695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 }
697 if (*(args[1]) == 0) {
698 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 }
702 global.nbproc = atol(args[1]);
703 }
704 else if (!strcmp(args[0], "maxconn")) {
705 if (global.maxconn != 0) {
706 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT;
708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 }
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 }
715 global.maxconn = atol(args[1]);
716#ifdef SYSTEM_MAXCONN
717 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
718 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);
719 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200720 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722#endif /* SYSTEM_MAXCONN */
723 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200724 else if (!strcmp(args[0], "maxsslconn")) {
725#ifdef USE_OPENSSL
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.maxsslconn = atol(args[1]);
732#else
733 if (*(args[1]) == 0) {
734 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738#endif
739 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200740 else if (!strcmp(args[0], "maxconnrate")) {
741 if (global.cps_lim != 0) {
742 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT;
744 goto out;
745 }
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 global.cps_lim = atol(args[1]);
752 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100753 else if (!strcmp(args[0], "maxpipes")) {
754 if (global.maxpipes != 0) {
755 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT;
757 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100758 }
759 if (*(args[1]) == 0) {
760 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100763 }
764 global.maxpipes = atol(args[1]);
765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766 else if (!strcmp(args[0], "ulimit-n")) {
767 if (global.rlimit_nofile != 0) {
768 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 err_code |= ERR_ALERT;
770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 }
772 if (*(args[1]) == 0) {
773 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT | ERR_FATAL;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 global.rlimit_nofile = atol(args[1]);
778 }
779 else if (!strcmp(args[0], "chroot")) {
780 if (global.chroot != NULL) {
781 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT;
783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 if (*(args[1]) == 0) {
786 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 }
790 global.chroot = strdup(args[1]);
791 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200792 else if (!strcmp(args[0], "description")) {
793 int i, len=0;
794 char *d;
795
796 if (!*args[1]) {
797 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
798 file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802
803 for(i=1; *args[i]; i++)
804 len += strlen(args[i])+1;
805
806 if (global.desc)
807 free(global.desc);
808
809 global.desc = d = (char *)calloc(1, len);
810
811 d += sprintf(d, "%s", args[1]);
812 for(i=2; *args[i]; i++)
813 d += sprintf(d, " %s", args[i]);
814 }
815 else if (!strcmp(args[0], "node")) {
816 int i;
817 char c;
818
819 for (i=0; args[1][i]; i++) {
820 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100821 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
822 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200823 break;
824 }
825
826 if (!i || args[1][i]) {
827 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
828 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
829 file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833
834 if (global.node)
835 free(global.node);
836
837 global.node = strdup(args[1]);
838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 else if (!strcmp(args[0], "pidfile")) {
840 if (global.pidfile != NULL) {
841 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200842 err_code |= ERR_ALERT;
843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 }
845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 }
850 global.pidfile = strdup(args[1]);
851 }
Emeric Bruned760922010-10-22 17:59:25 +0200852 else if (!strcmp(args[0], "unix-bind")) {
853 int cur_arg = 1;
854 while (*(args[cur_arg])) {
855 if (!strcmp(args[cur_arg], "prefix")) {
856 if (global.unix_bind.prefix != NULL) {
857 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
858 err_code |= ERR_ALERT;
859 cur_arg += 2;
860 continue;
861 }
862
863 if (*(args[cur_arg+1]) == 0) {
864 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
865 err_code |= ERR_ALERT | ERR_FATAL;
866 goto out;
867 }
868 global.unix_bind.prefix = strdup(args[cur_arg+1]);
869 cur_arg += 2;
870 continue;
871 }
872
873 if (!strcmp(args[cur_arg], "mode")) {
874
875 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
876 cur_arg += 2;
877 continue;
878 }
879
880 if (!strcmp(args[cur_arg], "uid")) {
881
882 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
883 cur_arg += 2;
884 continue;
885 }
886
887 if (!strcmp(args[cur_arg], "gid")) {
888
889 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
890 cur_arg += 2;
891 continue;
892 }
893
894 if (!strcmp(args[cur_arg], "user")) {
895 struct passwd *user;
896
897 user = getpwnam(args[cur_arg + 1]);
898 if (!user) {
899 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
900 file, linenum, args[0], args[cur_arg + 1 ]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904
905 global.unix_bind.ux.uid = user->pw_uid;
906 cur_arg += 2;
907 continue;
908 }
909
910 if (!strcmp(args[cur_arg], "group")) {
911 struct group *group;
912
913 group = getgrnam(args[cur_arg + 1]);
914 if (!group) {
915 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
916 file, linenum, args[0], args[cur_arg + 1 ]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
919 }
920
921 global.unix_bind.ux.gid = group->gr_gid;
922 cur_arg += 2;
923 continue;
924 }
925
Willy Tarreaub48f9582011-09-05 01:17:06 +0200926 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200927 file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 }
William Lallemand0f99e342011-10-12 17:50:54 +0200932 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
933 /* delete previous herited or defined syslog servers */
934 struct logsrv *back;
935 struct logsrv *tmp;
936
937 if (*(args[1]) != 0) {
938 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942
943 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
944 LIST_DEL(&tmp->list);
945 free(tmp);
946 }
947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200949 struct logsrv *logsrv;
950
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 if (*(args[1]) == 0 || *(args[2]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 }
William Lallemand0f99e342011-10-12 17:50:54 +0200956
957 logsrv = calloc(1, sizeof(struct logsrv));
958
959 logsrv->facility = get_log_facility(args[2]);
960 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200962 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200963 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 }
965
William Lallemand0f99e342011-10-12 17:50:54 +0200966 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200968 logsrv->level = get_log_level(args[3]);
969 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200972 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 }
975
William Lallemand0f99e342011-10-12 17:50:54 +0200976 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200977 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200978 logsrv->minlvl = get_log_level(args[4]);
979 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200980 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200981 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200982 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200983 }
984 }
985
Robert Tsai81ae1952007-12-05 10:47:29 +0100986 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100987 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100988 if (!sk) {
989 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100990 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100991 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200992 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100993 goto out;
994 }
William Lallemand0f99e342011-10-12 17:50:54 +0200995 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100996 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100997 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100998 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100999 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1000 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001001 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001002 goto out;
1003 }
William Lallemand0f99e342011-10-12 17:50:54 +02001004 logsrv->addr = *sk;
1005 if (!get_host_port(&logsrv->addr))
1006 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008
William Lallemand0f99e342011-10-12 17:50:54 +02001009 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001011 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1012 char *name;
1013 int len;
1014
1015 if (global.log_send_hostname != NULL) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1017 err_code |= ERR_ALERT;
1018 goto out;
1019 }
1020
1021 if (*(args[1]))
1022 name = args[1];
1023 else
1024 name = hostname;
1025
1026 len = strlen(name);
1027
1028 /* We'll add a space after the name to respect the log format */
1029 free(global.log_send_hostname);
1030 global.log_send_hostname = malloc(len + 2);
1031 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1032 }
Kevinm48936af2010-12-22 16:08:21 +00001033 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1034 if (*(args[1]) == 0) {
1035 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038 }
1039 free(global.log_tag);
1040 global.log_tag = strdup(args[1]);
1041 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001042 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1043 if (global.spread_checks != 0) {
1044 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 err_code |= ERR_ALERT;
1046 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001047 }
1048 if (*(args[1]) == 0) {
1049 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001052 }
1053 global.spread_checks = atol(args[1]);
1054 if (global.spread_checks < 0 || global.spread_checks > 50) {
1055 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 }
1059 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001060 struct cfg_kw_list *kwl;
1061 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001062 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001063
1064 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1065 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1066 if (kwl->kw[index].section != CFG_GLOBAL)
1067 continue;
1068 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1069 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001070 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001071 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001072 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001073 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001074 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001076 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001077 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001078 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_WARN;
1080 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001081 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001082 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001083 }
1084 }
1085 }
1086
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001090
Willy Tarreau058e9072009-07-20 09:30:05 +02001091 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001092 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001093 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094}
1095
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001096void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001098 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 defproxy.mode = PR_MODE_TCP;
1100 defproxy.state = PR_STNEW;
1101 defproxy.maxconn = cfg_maxpconn;
1102 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001103
1104 defproxy.defsrv.inter = DEF_CHKINTR;
1105 defproxy.defsrv.fastinter = 0;
1106 defproxy.defsrv.downinter = 0;
1107 defproxy.defsrv.rise = DEF_RISETIME;
1108 defproxy.defsrv.fall = DEF_FALLTIME;
1109 defproxy.defsrv.check_port = 0;
1110 defproxy.defsrv.maxqueue = 0;
1111 defproxy.defsrv.minconn = 0;
1112 defproxy.defsrv.maxconn = 0;
1113 defproxy.defsrv.slowstart = 0;
1114 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1115 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1116 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117}
1118
Willy Tarreauade5ec42010-01-28 19:33:49 +01001119
1120static int create_cond_regex_rule(const char *file, int line,
1121 struct proxy *px, int dir, int action, int flags,
1122 const char *cmd, const char *reg, const char *repl,
1123 const char **cond_start)
1124{
1125 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001126 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001127 const char *err;
1128 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001129 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001130
1131 if (px == &defproxy) {
1132 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto err;
1135 }
1136
1137 if (*reg == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto err;
1141 }
1142
1143 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1144 err_code |= ERR_WARN;
1145
Willy Tarreau5321c422010-01-28 20:35:13 +01001146 if (cond_start &&
1147 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001148 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1149 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1150 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto err;
1153 }
1154 }
1155 else if (cond_start && **cond_start) {
1156 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1157 file, line, cmd, *cond_start);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto err;
1160 }
1161
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001162 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001163 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001164 else
1165 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001166
Willy Tarreauade5ec42010-01-28 19:33:49 +01001167 preg = calloc(1, sizeof(regex_t));
1168 if (!preg) {
1169 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1170 err_code = ERR_ALERT | ERR_FATAL;
1171 goto err;
1172 }
1173
1174 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1175 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1176 err_code = ERR_ALERT | ERR_FATAL;
1177 goto err;
1178 }
1179
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001180 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001181 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001182 if (repl && err) {
1183 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1184 file, line, cmd, *err);
1185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto err;
1187 }
1188
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001189 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001190 err_code |= ERR_WARN;
1191
Willy Tarreauf4068b62012-05-08 17:37:49 +02001192 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001193 return err_code;
1194 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001195 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001196 free(preg);
1197 return err_code;
1198}
1199
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001201 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001202 * Returns the error code, 0 if OK, or any combination of :
1203 * - ERR_ABORT: must abort ASAP
1204 * - ERR_FATAL: we can continue parsing but not start the service
1205 * - ERR_WARN: a warning has been emitted
1206 * - ERR_ALERT: an alert has been emitted
1207 * Only the two first ones can stop processing, the two others are just
1208 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001210int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1211{
1212 static struct peers *curpeers = NULL;
1213 struct peer *newpeer = NULL;
1214 const char *err;
1215 int err_code = 0;
1216
1217 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1218
1219 err = invalid_char(args[1]);
1220 if (err) {
1221 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1222 file, linenum, *err, args[0], args[1]);
1223 err_code |= ERR_ALERT | ERR_FATAL;
1224 }
1225
1226 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1227 /*
1228 * If there are two proxies with the same name only following
1229 * combinations are allowed:
1230 */
1231 if (strcmp(curpeers->id, args[1]) == 0) {
1232 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1233 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1234 err_code |= ERR_WARN;
1235 }
1236 }
1237
1238 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1240 err_code |= ERR_ALERT | ERR_ABORT;
1241 goto out;
1242 }
1243
1244 curpeers->next = peers;
1245 peers = curpeers;
1246 curpeers->conf.file = file;
1247 curpeers->conf.line = linenum;
1248 curpeers->last_change = now.tv_sec;
1249 curpeers->id = strdup(args[1]);
1250 }
1251 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1252 char *rport, *raddr;
1253 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001254 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001255
1256 if (!*args[2]) {
1257 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1258 file, linenum, args[0]);
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 err = invalid_char(args[1]);
1264 if (err) {
1265 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1266 file, linenum, *err, args[1]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270
1271 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1273 err_code |= ERR_ALERT | ERR_ABORT;
1274 goto out;
1275 }
1276
1277 /* the peers are linked backwards first */
1278 curpeers->count++;
1279 newpeer->next = curpeers->remote;
1280 curpeers->remote = newpeer;
1281 newpeer->peers = curpeers;
1282 newpeer->conf.file = file;
1283 newpeer->conf.line = linenum;
1284
1285 newpeer->last_change = now.tv_sec;
1286 newpeer->id = strdup(args[1]);
1287
1288 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001289 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001290 if (rport) {
1291 *rport++ = 0;
1292 realport = atol(rport);
1293 }
1294 if (!realport) {
1295 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299
Willy Tarreaufab5a432011-03-04 15:31:53 +01001300 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001301 free(raddr);
1302 if (!sk) {
1303 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1304 err_code |= ERR_ALERT | ERR_FATAL;
1305 goto out;
1306 }
1307 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001308 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001309 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001310 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001311
1312 if (!sk) {
1313 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1314 file, linenum, newpeer->addr.ss_family, args[2]);
1315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
1317 }
1318
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001319 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001320
1321 if (strcmp(newpeer->id, localpeer) == 0) {
1322 /* Current is local peer, it define a frontend */
1323 newpeer->local = 1;
1324
1325 if (!curpeers->peers_fe) {
1326 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1328 err_code |= ERR_ALERT | ERR_ABORT;
1329 goto out;
1330 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001331
Willy Tarreau237250c2011-07-29 01:49:03 +02001332 init_new_proxy(curpeers->peers_fe);
1333 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001334
1335 curpeers->peers_fe->last_change = now.tv_sec;
1336 curpeers->peers_fe->id = strdup(args[1]);
1337 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001338 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001339 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1340 curpeers->peers_fe->timeout.connect = 5000;
1341 curpeers->peers_fe->accept = peer_accept;
1342 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001343 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001344 err_code |= ERR_FATAL;
1345 goto out;
1346 }
1347 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1348 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1349 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1350 curpeers->peers_fe->listen->accept = session_accept;
1351 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1352 curpeers->peers_fe->listen->handler = process_session;
1353 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001354 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1355 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001356 }
1357 }
1358 } /* neither "peer" nor "peers" */
1359 else if (*args[0] != 0) {
1360 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
1363 }
1364
1365out:
1366 return err_code;
1367}
1368
1369
Willy Tarreau3842f002009-06-14 11:39:52 +02001370int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371{
1372 static struct proxy *curproxy = NULL;
1373 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001374 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001375 int rc;
1376 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001377 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001378 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001379 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001380 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381
Willy Tarreau977b8e42006-12-29 14:19:17 +01001382 if (!strcmp(args[0], "listen"))
1383 rc = PR_CAP_LISTEN;
1384 else if (!strcmp(args[0], "frontend"))
1385 rc = PR_CAP_FE | PR_CAP_RS;
1386 else if (!strcmp(args[0], "backend"))
1387 rc = PR_CAP_BE | PR_CAP_RS;
1388 else if (!strcmp(args[0], "ruleset"))
1389 rc = PR_CAP_RS;
1390 else
1391 rc = PR_CAP_NONE;
1392
1393 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 if (!*args[1]) {
1395 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1396 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001398 err_code |= ERR_ALERT | ERR_ABORT;
1399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001401
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001402 err = invalid_char(args[1]);
1403 if (err) {
1404 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1405 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001406 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001407 }
1408
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001409 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1410 /*
1411 * If there are two proxies with the same name only following
1412 * combinations are allowed:
1413 *
1414 * listen backend frontend ruleset
1415 * listen - - - -
1416 * backend - - OK -
1417 * frontend - OK - -
1418 * ruleset - - - -
1419 */
1420
1421 if (!strcmp(curproxy->id, args[1]) &&
1422 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1423 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001424 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1425 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1426 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001427 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001428 }
1429 }
1430
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1432 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001433 err_code |= ERR_ALERT | ERR_ABORT;
1434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001436
Willy Tarreau97cb7802010-01-03 20:23:58 +01001437 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 curproxy->next = proxy;
1439 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001440 curproxy->conf.file = file;
1441 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001442 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001444 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445
1446 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001447 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001448 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001449 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001450 err_code |= ERR_FATAL;
1451 goto out;
1452 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001453 new = curproxy->listen;
1454 while (new != last) {
1455 new->conf.file = file;
1456 new->conf.line = linenum;
1457 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001458 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 }
1461
1462 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001463 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001464 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001465
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001468 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001469 curproxy->no_options = defproxy.no_options;
1470 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001471 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001472 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001473 curproxy->except_net = defproxy.except_net;
1474 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001475 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001476 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001478 if (defproxy.fwdfor_hdr_len) {
1479 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1480 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1481 }
1482
Willy Tarreaub86db342009-11-30 11:50:16 +01001483 if (defproxy.orgto_hdr_len) {
1484 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1485 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1486 }
1487
Mark Lamourinec2247f02012-01-04 13:02:01 -05001488 if (defproxy.server_id_hdr_len) {
1489 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1490 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1491 }
1492
Willy Tarreau977b8e42006-12-29 14:19:17 +01001493 if (curproxy->cap & PR_CAP_FE) {
1494 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001495 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001496 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497
1498 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001499 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1500 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001501
1502 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504
Willy Tarreau977b8e42006-12-29 14:19:17 +01001505 if (curproxy->cap & PR_CAP_BE) {
1506 curproxy->fullconn = defproxy.fullconn;
1507 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001509 if (defproxy.check_req) {
1510 curproxy->check_req = calloc(1, defproxy.check_len);
1511 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1512 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001513 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001514
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001515 if (defproxy.expect_str) {
1516 curproxy->expect_str = strdup(defproxy.expect_str);
1517 if (defproxy.expect_regex) {
1518 /* note: this regex is known to be valid */
1519 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1520 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1521 }
1522 }
1523
Willy Tarreau67402132012-05-31 20:40:20 +02001524 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001525 if (defproxy.cookie_name)
1526 curproxy->cookie_name = strdup(defproxy.cookie_name);
1527 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001528 if (defproxy.cookie_domain)
1529 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001530
Willy Tarreau31936852010-10-06 16:59:56 +02001531 if (defproxy.cookie_maxidle)
1532 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1533
1534 if (defproxy.cookie_maxlife)
1535 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1536
Emeric Brun647caf12009-06-30 17:57:00 +02001537 if (defproxy.rdp_cookie_name)
1538 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1539 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1540
Willy Tarreau01732802007-11-01 22:48:15 +01001541 if (defproxy.url_param_name)
1542 curproxy->url_param_name = strdup(defproxy.url_param_name);
1543 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001544
Benoitaffb4812009-03-25 13:02:10 +01001545 if (defproxy.hh_name)
1546 curproxy->hh_name = strdup(defproxy.hh_name);
1547 curproxy->hh_len = defproxy.hh_len;
1548 curproxy->hh_match_domain = defproxy.hh_match_domain;
1549
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001550 if (defproxy.iface_name)
1551 curproxy->iface_name = strdup(defproxy.iface_name);
1552 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001555 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001556 if (defproxy.capture_name)
1557 curproxy->capture_name = strdup(defproxy.capture_name);
1558 curproxy->capture_namelen = defproxy.capture_namelen;
1559 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561
Willy Tarreau977b8e42006-12-29 14:19:17 +01001562 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001563 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001564 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001565 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001566 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567 curproxy->uri_auth = defproxy.uri_auth;
1568 curproxy->mon_net = defproxy.mon_net;
1569 curproxy->mon_mask = defproxy.mon_mask;
1570 if (defproxy.monitor_uri)
1571 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1572 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001573 if (defproxy.defbe.name)
1574 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001575
1576 /* get either a pointer to the logformat string or a copy of it */
1577 curproxy->logformat_string = defproxy.logformat_string;
1578 if (curproxy->logformat_string &&
1579 curproxy->logformat_string != default_http_log_format &&
1580 curproxy->logformat_string != default_tcp_log_format &&
1581 curproxy->logformat_string != clf_http_log_format)
1582 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001583 }
1584
1585 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001586 curproxy->timeout.connect = defproxy.timeout.connect;
1587 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001588 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001589 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001590 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001591 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001592 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001593 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001594 curproxy->source_addr = defproxy.source_addr;
1595 }
1596
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001598
1599 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001600 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001601 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001602 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001603 LIST_INIT(&node->list);
1604 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1605 }
1606
Willy Tarreau196729e2012-05-31 19:30:26 +02001607 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1608 if (curproxy->uniqueid_format_string)
1609 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001610
1611 /* copy default header unique id */
1612 if (defproxy.header_unique_id)
1613 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1614
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001616 curproxy->conf.used_listener_id = EB_ROOT;
1617 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001618
Willy Tarreau93893792009-07-23 13:19:11 +02001619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 }
1621 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1622 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001623 /* FIXME-20070101: we should do this too at the end of the
1624 * config parsing to free all default values.
1625 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001626 free(defproxy.check_req);
1627 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001628 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001629 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001630 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001631 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001632 free(defproxy.capture_name);
1633 free(defproxy.monitor_uri);
1634 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001635 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001636 free(defproxy.fwdfor_hdr_name);
1637 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001638 free(defproxy.orgto_hdr_name);
1639 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001640 free(defproxy.server_id_hdr_name);
1641 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001642 free(defproxy.expect_str);
1643 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001644
Willy Tarreau39b06652012-06-01 10:58:06 +02001645 if (defproxy.logformat_string != default_http_log_format &&
1646 defproxy.logformat_string != default_tcp_log_format &&
1647 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001648 free(defproxy.logformat_string);
1649
1650 free(defproxy.uniqueid_format_string);
1651
Willy Tarreaua534fea2008-08-03 12:19:50 +02001652 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001653 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001654
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 /* we cannot free uri_auth because it might already be used */
1656 init_default_instance();
1657 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001658 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660 }
1661 else if (curproxy == NULL) {
1662 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 }
1666
Willy Tarreau977b8e42006-12-29 14:19:17 +01001667
1668 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001670 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001671 int cur_arg;
1672
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 if (curproxy == &defproxy) {
1674 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001675 err_code |= ERR_ALERT | ERR_FATAL;
1676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001677 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001678 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001679 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001680
Emeric Bruned760922010-10-22 17:59:25 +02001681 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001682 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001687
1688 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001689
1690 /* NOTE: the following line might create several listeners if there
1691 * are comma-separated IPs or port ranges. So all further processing
1692 * will have to be applied to all listeners created after last_listen.
1693 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001694 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
1697 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001698
Willy Tarreau90a570f2009-10-04 20:54:54 +02001699 new_listen = curproxy->listen;
1700 while (new_listen != last_listen) {
1701 new_listen->conf.file = file;
1702 new_listen->conf.line = linenum;
1703 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001704 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001705 }
1706
Emeric Bruned760922010-10-22 17:59:25 +02001707 /* Set default global rights and owner for unix bind */
1708 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1709 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1710 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001711 cur_arg = 2;
1712 while (*(args[cur_arg])) {
1713 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1714#ifdef SO_BINDTODEVICE
1715 struct listener *l;
1716
Emeric Bruned760922010-10-22 17:59:25 +02001717 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1718 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1719 file, linenum, args[0], args[cur_arg]);
1720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
1722 }
1723
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001724 if (!*args[cur_arg + 1]) {
1725 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001727 err_code |= ERR_ALERT | ERR_FATAL;
1728 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001729 }
1730
1731 for (l = curproxy->listen; l != last_listen; l = l->next)
1732 l->interface = strdup(args[cur_arg + 1]);
1733
1734 global.last_checks |= LSTCHK_NETADM;
1735
1736 cur_arg += 2;
1737 continue;
1738#else
1739 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1740 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001741 err_code |= ERR_ALERT | ERR_FATAL;
1742 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001743#endif
1744 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001745 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1746#ifdef TCP_MAXSEG
1747 struct listener *l;
1748 int mss;
1749
Emeric Bruned760922010-10-22 17:59:25 +02001750 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1751 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1752 file, linenum, args[0], args[cur_arg]);
1753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
1755 }
1756
Willy Tarreaube1b9182009-06-14 18:48:19 +02001757 if (!*args[cur_arg + 1]) {
1758 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1759 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001760 err_code |= ERR_ALERT | ERR_FATAL;
1761 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001762 }
1763
Willy Tarreau48a7e722010-12-24 15:26:39 +01001764 mss = atoi(args[cur_arg + 1]);
1765 if (!mss || abs(mss) > 65535) {
1766 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001768 err_code |= ERR_ALERT | ERR_FATAL;
1769 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001770 }
1771
1772 for (l = curproxy->listen; l != last_listen; l = l->next)
1773 l->maxseg = mss;
1774
1775 cur_arg += 2;
1776 continue;
1777#else
1778 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1779 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001782#endif
1783 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001784
1785 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1786#ifdef TCP_DEFER_ACCEPT
1787 struct listener *l;
1788
1789 for (l = curproxy->listen; l != last_listen; l = l->next)
1790 l->options |= LI_O_DEF_ACCEPT;
1791
1792 cur_arg ++;
1793 continue;
1794#else
1795 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1796 file, linenum, args[0], args[cur_arg]);
1797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
1799#endif
1800 }
1801
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001802 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001803#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001804 struct listener *l;
1805
Emeric Bruned760922010-10-22 17:59:25 +02001806 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1807 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1808 file, linenum, args[0], args[cur_arg]);
1809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
1811 }
1812
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001813 for (l = curproxy->listen; l != last_listen; l = l->next)
1814 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001815
1816 cur_arg ++;
1817 continue;
1818#else
1819 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1820 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001823#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001824 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001825
Willy Tarreau32368ce2012-09-06 11:10:55 +02001826 if (!strcmp(args[cur_arg], "maxconn")) {
1827 struct listener *l;
1828 int val;
1829
1830 if (!*args[cur_arg + 1]) {
1831 Alert("parsing [%s:%d] : '%s' : missing maxconn value.\n",
1832 file, linenum, args[0]);
1833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
1835 }
1836
1837 val = atol(args[cur_arg + 1]);
1838 if (val <= 0) {
1839 Alert("parsing [%s:%d] : '%s' : invalid maxconn value %d, must be > 0.\n",
1840 file, linenum, args[0], val);
1841 err_code |= ERR_ALERT | ERR_FATAL;
1842 goto out;
1843 }
1844
1845 for (l = curproxy->listen; l != last_listen; l = l->next)
1846 l->maxconn = val;
1847
1848 cur_arg += 2;
1849 continue;
1850 }
1851
1852 if (!strcmp(args[cur_arg], "backlog")) {
1853 struct listener *l;
1854 int val;
1855
1856 if (!*args[cur_arg + 1]) {
1857 Alert("parsing [%s:%d] : '%s' : missing backlog value.\n",
1858 file, linenum, args[0]);
1859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
1861 }
1862
1863 val = atol(args[cur_arg + 1]);
1864 if (val <= 0) {
1865 Alert("parsing [%s:%d] : '%s' : invalid backlog value %d, must be > 0.\n",
1866 file, linenum, args[0], val);
1867 err_code |= ERR_ALERT | ERR_FATAL;
1868 goto out;
1869 }
1870
1871 for (l = curproxy->listen; l != last_listen; l = l->next)
1872 l->backlog = val;
1873
1874 cur_arg += 2;
1875 continue;
1876 }
1877
Willy Tarreau50acaaa2012-09-06 14:26:36 +02001878 if (!strcmp(args[cur_arg], "nice")) {
1879 struct listener *l;
1880 int val;
1881
1882 if (!*args[cur_arg + 1]) {
1883 Alert("parsing [%s:%d] : '%s' : missing nice value.\n",
1884 file, linenum, args[0]);
1885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
1887 }
1888
1889 val = atol(args[cur_arg + 1]);
1890 if (val < -1024 || val > 1024) {
1891 Alert("parsing [%s:%d] : '%s' : invalid nice value %d, allowed range is -1024..1024.\n",
1892 file, linenum, args[0], val);
1893 err_code |= ERR_ALERT | ERR_FATAL;
1894 goto out;
1895 }
1896
1897 for (l = curproxy->listen; l != last_listen; l = l->next)
1898 l->nice = val;
1899
1900 cur_arg += 2;
1901 continue;
1902 }
1903
Emeric Brun6e159292012-05-18 16:32:13 +02001904 if (!strcmp(args[cur_arg], "ssl")) { /* use ssl certificate */
1905#ifdef USE_OPENSSL
1906 struct listener *l;
1907
1908 if (!*args[cur_arg + 1]) {
1909 Alert("parsing [%s:%d] : '%s' : missing certificate.\n",
1910 file, linenum, args[0]);
1911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
1913 }
1914
1915 for (l = curproxy->listen; l != last_listen; l = l->next)
1916 l->ssl_cert = strdup(args[cur_arg + 1]);
1917
1918 cur_arg += 2;
1919 continue;
1920#else
1921 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1922 file, linenum, args[0], args[cur_arg]);
1923 err_code |= ERR_ALERT | ERR_FATAL;
1924 goto out;
1925#endif
1926 }
1927
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001928 if (!strcmp(args[cur_arg], "ciphers")) { /* set cipher suite */
1929#ifdef USE_OPENSSL
1930 struct listener *l;
1931
1932 if (!*args[cur_arg + 1]) {
1933 Alert("parsing [%s:%d] : '%s' : missing cipher suite.\n",
1934 file, linenum, args[0]);
1935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
1937 }
1938
1939 for (l = curproxy->listen; l != last_listen; l = l->next)
1940 l->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
1941
1942 cur_arg += 2;
1943 continue;
1944#else
1945 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1946 file, linenum, args[0], args[cur_arg]);
1947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
1949#endif
1950 }
1951
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001952 if (!strcmp(args[cur_arg], "nosslv3")) { /* disable SSLv3 */
1953#ifdef USE_OPENSSL
1954 struct listener *l;
1955
1956 for (l = curproxy->listen; l != last_listen; l = l->next)
1957 l->ssl_ctx.nosslv3 = 1;
1958
1959 cur_arg += 1;
1960 continue;
1961#else
1962 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1963 file, linenum, args[0], args[cur_arg]);
1964 err_code |= ERR_ALERT | ERR_FATAL;
1965 goto out;
1966#endif
1967 }
1968
1969 if (!strcmp(args[cur_arg], "notlsv1")) { /* disable TLSv1 */
1970#ifdef USE_OPENSSL
1971 struct listener *l;
1972
1973 for (l = curproxy->listen; l != last_listen; l = l->next)
1974 l->ssl_ctx.notlsv1 = 1;
1975
1976 cur_arg += 1;
1977 continue;
1978#else
1979 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1980 file, linenum, args[0], args[cur_arg]);
1981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
1983#endif
1984 }
1985
David BERARDe566ecb2012-09-04 15:15:13 +02001986 if (!strcmp(args[cur_arg], "prefer-server-ciphers")) { /* Prefert server ciphers */
1987#if defined (USE_OPENSSL) && defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
1988 struct listener *l;
1989
1990 for (l = curproxy->listen; l != last_listen; l = l->next)
1991 l->ssl_ctx.prefer_server_ciphers = 1;
1992
1993 cur_arg += 1;
1994 continue;
1995#else
1996 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1997 file, linenum, args[0], args[cur_arg]);
1998 err_code |= ERR_ALERT | ERR_FATAL;
1999 goto out;
2000#endif
2001 }
2002
Willy Tarreau8a956912010-10-15 14:27:08 +02002003 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
2004 struct listener *l;
2005
2006 for (l = curproxy->listen; l != last_listen; l = l->next)
2007 l->options |= LI_O_ACC_PROXY;
2008
2009 cur_arg ++;
2010 continue;
2011 }
2012
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002013 if (!strcmp(args[cur_arg], "name")) {
2014 struct listener *l;
2015
2016 for (l = curproxy->listen; l != last_listen; l = l->next)
2017 l->name = strdup(args[cur_arg + 1]);
2018
2019 cur_arg += 2;
2020 continue;
2021 }
2022
2023 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002024 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002025 struct listener *l;
2026
2027 if (curproxy->listen->next != last_listen) {
2028 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
2029 file, linenum, args[cur_arg]);
2030 err_code |= ERR_ALERT | ERR_FATAL;
2031 goto out;
2032 }
2033
2034 if (!*args[cur_arg + 1]) {
2035 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2036 file, linenum, args[cur_arg]);
2037 err_code |= ERR_ALERT | ERR_FATAL;
2038 goto out;
2039 }
2040
2041 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002042 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002043
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002044 if (curproxy->listen->luid <= 0) {
2045 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002046 file, linenum);
2047 err_code |= ERR_ALERT | ERR_FATAL;
2048 goto out;
2049 }
2050
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002051 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
2052 if (node) {
2053 l = container_of(node, struct listener, conf.id);
2054 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
2055 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
2056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
2058 }
2059 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
2060
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002061 cur_arg += 2;
2062 continue;
2063 }
2064
Emeric Bruned760922010-10-22 17:59:25 +02002065 if (!strcmp(args[cur_arg], "mode")) {
2066
2067 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2068 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2069 file, linenum, args[0], args[cur_arg]);
2070 err_code |= ERR_ALERT | ERR_FATAL;
2071 goto out;
2072 }
2073
2074 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
2075
2076 cur_arg += 2;
2077 continue;
2078 }
2079
2080 if (!strcmp(args[cur_arg], "uid")) {
2081
2082 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2083 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2084 file, linenum, args[0], args[cur_arg]);
2085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
2087 }
2088
2089 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
2090 cur_arg += 2;
2091 continue;
2092 }
2093
2094 if (!strcmp(args[cur_arg], "gid")) {
2095
2096 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2097 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2098 file, linenum, args[0], args[cur_arg]);
2099 err_code |= ERR_ALERT | ERR_FATAL;
2100 goto out;
2101 }
2102
2103 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
2104 cur_arg += 2;
2105 continue;
2106 }
2107
2108 if (!strcmp(args[cur_arg], "user")) {
2109 struct passwd *user;
2110
2111 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2112 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2113 file, linenum, args[0], args[cur_arg]);
2114 err_code |= ERR_ALERT | ERR_FATAL;
2115 goto out;
2116 }
2117 user = getpwnam(args[cur_arg + 1]);
2118 if (!user) {
2119 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
2120 file, linenum, args[0], args[cur_arg + 1 ]);
2121 err_code |= ERR_ALERT | ERR_FATAL;
2122 goto out;
2123 }
2124
2125 curproxy->listen->perm.ux.uid = user->pw_uid;
2126 cur_arg += 2;
2127 continue;
2128 }
2129
2130 if (!strcmp(args[cur_arg], "group")) {
2131 struct group *group;
2132
2133 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2134 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2135 file, linenum, args[0], args[cur_arg]);
2136 err_code |= ERR_ALERT | ERR_FATAL;
2137 goto out;
2138 }
2139 group = getgrnam(args[cur_arg + 1]);
2140 if (!group) {
2141 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
2142 file, linenum, args[0], args[cur_arg + 1 ]);
2143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
2145 }
2146
2147 curproxy->listen->perm.ux.gid = group->gr_gid;
2148 cur_arg += 2;
2149 continue;
2150 }
2151
Willy Tarreaub48f9582011-09-05 01:17:06 +02002152 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 +01002153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002156 }
Willy Tarreau93893792009-07-23 13:19:11 +02002157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 }
2159 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2160 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2161 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2162 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002163 err_code |= ERR_ALERT | ERR_FATAL;
2164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002165 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002166 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002167 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002168
Willy Tarreaubaaee002006-06-26 02:48:02 +02002169 /* flush useless bits */
2170 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002173 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002174 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002175 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002176
Willy Tarreau1c47f852006-07-09 08:22:27 +02002177 if (!*args[1]) {
2178 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2179 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002182 }
2183
Willy Tarreaua534fea2008-08-03 12:19:50 +02002184 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002185 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002186 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002187 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002188 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2189
Willy Tarreau93893792009-07-23 13:19:11 +02002190 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2193 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2194 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2195 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2196 else {
2197 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002198 err_code |= ERR_ALERT | ERR_FATAL;
2199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002200 }
2201 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002202 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002203 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002204
2205 if (curproxy == &defproxy) {
2206 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2207 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002208 err_code |= ERR_ALERT | ERR_FATAL;
2209 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002210 }
2211
2212 if (!*args[1]) {
2213 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2214 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002217 }
2218
2219 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002220 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002221
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002222 if (curproxy->uuid <= 0) {
2223 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002224 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002225 err_code |= ERR_ALERT | ERR_FATAL;
2226 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002227 }
2228
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002229 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2230 if (node) {
2231 struct proxy *target = container_of(node, struct proxy, conf.id);
2232 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2233 file, linenum, proxy_type_str(curproxy), curproxy->id,
2234 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
2237 }
2238 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002239 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002240 else if (!strcmp(args[0], "description")) {
2241 int i, len=0;
2242 char *d;
2243
Cyril Bonté99ed3272010-01-24 23:29:44 +01002244 if (curproxy == &defproxy) {
2245 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2246 file, linenum, args[0]);
2247 err_code |= ERR_ALERT | ERR_FATAL;
2248 goto out;
2249 }
2250
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002251 if (!*args[1]) {
2252 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2253 file, linenum, args[0]);
2254 return -1;
2255 }
2256
2257 for(i=1; *args[i]; i++)
2258 len += strlen(args[i])+1;
2259
2260 d = (char *)calloc(1, len);
2261 curproxy->desc = d;
2262
2263 d += sprintf(d, "%s", args[1]);
2264 for(i=2; *args[i]; i++)
2265 d += sprintf(d, " %s", args[i]);
2266
2267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2269 curproxy->state = PR_STSTOPPED;
2270 }
2271 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2272 curproxy->state = PR_STNEW;
2273 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002274 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2275 int cur_arg = 1;
2276 unsigned int set = 0;
2277
2278 while (*args[cur_arg]) {
2279 int u;
2280 if (strcmp(args[cur_arg], "all") == 0) {
2281 set = 0;
2282 break;
2283 }
2284 else if (strcmp(args[cur_arg], "odd") == 0) {
2285 set |= 0x55555555;
2286 }
2287 else if (strcmp(args[cur_arg], "even") == 0) {
2288 set |= 0xAAAAAAAA;
2289 }
2290 else {
2291 u = str2uic(args[cur_arg]);
2292 if (u < 1 || u > 32) {
2293 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2294 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002297 }
2298 if (u > global.nbproc) {
2299 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2300 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002301 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002302 }
2303 set |= 1 << (u - 1);
2304 }
2305 cur_arg++;
2306 }
2307 curproxy->bind_proc = set;
2308 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002309 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002310 if (curproxy == &defproxy) {
2311 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002312 err_code |= ERR_ALERT | ERR_FATAL;
2313 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002314 }
2315
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002316 err = invalid_char(args[1]);
2317 if (err) {
2318 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2319 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002320 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002321 }
2322
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002323 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2324 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2325 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002328 }
2329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2331 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332
Willy Tarreau977b8e42006-12-29 14:19:17 +01002333 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002334 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002335
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 if (*(args[1]) == 0) {
2337 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2338 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002342
Willy Tarreau67402132012-05-31 20:40:20 +02002343 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002344 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002345 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002346 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 curproxy->cookie_name = strdup(args[1]);
2348 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002349
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 cur_arg = 2;
2351 while (*(args[cur_arg])) {
2352 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002353 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 }
2355 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002356 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 }
2358 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002359 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 }
2361 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002362 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 }
2364 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002365 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002367 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002368 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002371 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002373 else if (!strcmp(args[cur_arg], "httponly")) {
2374 curproxy->ck_opts |= PR_CK_HTTPONLY;
2375 }
2376 else if (!strcmp(args[cur_arg], "secure")) {
2377 curproxy->ck_opts |= PR_CK_SECURE;
2378 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002379 else if (!strcmp(args[cur_arg], "domain")) {
2380 if (!*args[cur_arg + 1]) {
2381 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2382 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002385 }
2386
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002387 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002388 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002389 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2390 " dots nor does not start with a dot."
2391 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002392 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002393 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002394 }
2395
2396 err = invalid_domainchar(args[cur_arg + 1]);
2397 if (err) {
2398 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2399 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002402 }
2403
Willy Tarreau68a897b2009-12-03 23:28:34 +01002404 if (!curproxy->cookie_domain) {
2405 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2406 } else {
2407 /* one domain was already specified, add another one by
2408 * building the string which will be returned along with
2409 * the cookie.
2410 */
2411 char *new_ptr;
2412 int new_len = strlen(curproxy->cookie_domain) +
2413 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2414 new_ptr = malloc(new_len);
2415 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2416 free(curproxy->cookie_domain);
2417 curproxy->cookie_domain = new_ptr;
2418 }
Willy Tarreau31936852010-10-06 16:59:56 +02002419 cur_arg++;
2420 }
2421 else if (!strcmp(args[cur_arg], "maxidle")) {
2422 unsigned int maxidle;
2423 const char *res;
2424
2425 if (!*args[cur_arg + 1]) {
2426 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2427 file, linenum, args[cur_arg]);
2428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
2430 }
2431
2432 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2433 if (res) {
2434 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2435 file, linenum, *res, args[cur_arg]);
2436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
2438 }
2439 curproxy->cookie_maxidle = maxidle;
2440 cur_arg++;
2441 }
2442 else if (!strcmp(args[cur_arg], "maxlife")) {
2443 unsigned int maxlife;
2444 const char *res;
2445
2446 if (!*args[cur_arg + 1]) {
2447 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2448 file, linenum, args[cur_arg]);
2449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
2451 }
2452
2453 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2454 if (res) {
2455 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2456 file, linenum, *res, args[cur_arg]);
2457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
2459 }
2460 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002461 cur_arg++;
2462 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002464 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 +02002465 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 }
2469 cur_arg++;
2470 }
Willy Tarreau67402132012-05-31 20:40:20 +02002471 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2473 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002474 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 }
2476
Willy Tarreau67402132012-05-31 20:40:20 +02002477 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2479 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002482
Willy Tarreau67402132012-05-31 20:40:20 +02002483 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002484 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2485 file, linenum);
2486 err_code |= ERR_ALERT | ERR_FATAL;
2487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002489 else if (!strcmp(args[0], "persist")) { /* persist */
2490 if (*(args[1]) == 0) {
2491 Alert("parsing [%s:%d] : missing persist method.\n",
2492 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002495 }
2496
2497 if (!strncmp(args[1], "rdp-cookie", 10)) {
2498 curproxy->options2 |= PR_O2_RDPC_PRST;
2499
Emeric Brunb982a3d2010-01-04 15:45:53 +01002500 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002501 const char *beg, *end;
2502
2503 beg = args[1] + 11;
2504 end = strchr(beg, ')');
2505
2506 if (!end || end == beg) {
2507 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2508 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002511 }
2512
2513 free(curproxy->rdp_cookie_name);
2514 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2515 curproxy->rdp_cookie_len = end-beg;
2516 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002517 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002518 free(curproxy->rdp_cookie_name);
2519 curproxy->rdp_cookie_name = strdup("msts");
2520 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2521 }
2522 else { /* syntax */
2523 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2524 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002527 }
2528 }
2529 else {
2530 Alert("parsing [%s:%d] : unknown persist method.\n",
2531 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002534 }
2535 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002537 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002539 if (curproxy == &defproxy) {
2540 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
2543 }
2544
Willy Tarreau977b8e42006-12-29 14:19:17 +01002545 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002547
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002549 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
2554 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002555 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 curproxy->appsession_name = strdup(args[1]);
2557 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2558 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002559 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2560 if (err) {
2561 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2562 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002565 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002566 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002567
Willy Tarreau51041c72007-09-09 21:56:53 +02002568 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2569 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_ABORT;
2571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002573
2574 cur_arg = 6;
2575 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002576 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2577 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002578 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002579 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002580 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002581 } else if (!strcmp(args[cur_arg], "prefix")) {
2582 curproxy->options2 |= PR_O2_AS_PFX;
2583 } else if (!strcmp(args[cur_arg], "mode")) {
2584 if (!*args[cur_arg + 1]) {
2585 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2586 file, linenum, args[0], args[cur_arg]);
2587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
2589 }
2590
2591 cur_arg++;
2592 if (!strcmp(args[cur_arg], "query-string")) {
2593 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2594 curproxy->options2 |= PR_O2_AS_M_QS;
2595 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2596 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2597 curproxy->options2 |= PR_O2_AS_M_PP;
2598 } else {
2599 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
2602 }
2603 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002604 cur_arg++;
2605 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 } /* Url App Session */
2607 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002608 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002609 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002610
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002612 if (curproxy == &defproxy) {
2613 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
2616 }
2617
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 if (*(args[4]) == 0) {
2619 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2620 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002624 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625 curproxy->capture_name = strdup(args[2]);
2626 curproxy->capture_namelen = strlen(curproxy->capture_name);
2627 curproxy->capture_len = atol(args[4]);
2628 if (curproxy->capture_len >= CAPTURE_LEN) {
2629 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2630 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 curproxy->capture_len = CAPTURE_LEN - 1;
2633 }
2634 curproxy->to_log |= LW_COOKIE;
2635 }
2636 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2637 struct cap_hdr *hdr;
2638
2639 if (curproxy == &defproxy) {
2640 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 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 }
2644
2645 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2646 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2647 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 }
2651
2652 hdr = calloc(sizeof(struct cap_hdr), 1);
2653 hdr->next = curproxy->req_cap;
2654 hdr->name = strdup(args[3]);
2655 hdr->namelen = strlen(args[3]);
2656 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002657 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 hdr->index = curproxy->nb_req_cap++;
2659 curproxy->req_cap = hdr;
2660 curproxy->to_log |= LW_REQHDR;
2661 }
2662 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2663 struct cap_hdr *hdr;
2664
2665 if (curproxy == &defproxy) {
2666 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 +02002667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669 }
2670
2671 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2672 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2673 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 }
2677 hdr = calloc(sizeof(struct cap_hdr), 1);
2678 hdr->next = curproxy->rsp_cap;
2679 hdr->name = strdup(args[3]);
2680 hdr->namelen = strlen(args[3]);
2681 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002682 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683 hdr->index = curproxy->nb_rsp_cap++;
2684 curproxy->rsp_cap = hdr;
2685 curproxy->to_log |= LW_RSPHDR;
2686 }
2687 else {
2688 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2689 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 }
2693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002695 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002697
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 if (*(args[1]) == 0) {
2699 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2700 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 }
2704 curproxy->conn_retries = atol(args[1]);
2705 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002706 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002707 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002708
2709 if (curproxy == &defproxy) {
2710 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
2713 }
2714
Willy Tarreauff011f22011-01-06 17:51:27 +01002715 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 +01002716 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2717 file, linenum, args[0]);
2718 err_code |= ERR_WARN;
2719 }
2720
Willy Tarreauff011f22011-01-06 17:51:27 +01002721 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002722
Willy Tarreauff011f22011-01-06 17:51:27 +01002723 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002724 err_code |= ERR_ALERT | ERR_ABORT;
2725 goto out;
2726 }
2727
Willy Tarreauff011f22011-01-06 17:51:27 +01002728 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2729 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002730 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002731 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2732 /* set the header name and length into the proxy structure */
2733 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2734 err_code |= ERR_WARN;
2735
2736 if (!*args[1]) {
2737 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2738 file, linenum, args[0]);
2739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
2741 }
2742
2743 /* set the desired header name */
2744 free(curproxy->server_id_hdr_name);
2745 curproxy->server_id_hdr_name = strdup(args[1]);
2746 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2747 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002748 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002749 if (curproxy == &defproxy) {
2750 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002753 }
2754
Willy Tarreauef6494c2010-01-28 17:12:36 +01002755 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002756 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2757 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002760 }
2761
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002762 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2763 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2764 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002767 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002768
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002769 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002770 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002771 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002772 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002773 struct redirect_rule *rule;
2774 int cur_arg;
2775 int type = REDIRECT_TYPE_NONE;
2776 int code = 302;
2777 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002778 char *cookie = NULL;
2779 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002780 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002781
Cyril Bonté99ed3272010-01-24 23:29:44 +01002782 if (curproxy == &defproxy) {
2783 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2784 err_code |= ERR_ALERT | ERR_FATAL;
2785 goto out;
2786 }
2787
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002788 cur_arg = 1;
2789 while (*(args[cur_arg])) {
2790 if (!strcmp(args[cur_arg], "location")) {
2791 if (!*args[cur_arg + 1]) {
2792 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2793 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002796 }
2797
2798 type = REDIRECT_TYPE_LOCATION;
2799 cur_arg++;
2800 destination = args[cur_arg];
2801 }
2802 else if (!strcmp(args[cur_arg], "prefix")) {
2803 if (!*args[cur_arg + 1]) {
2804 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2805 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002808 }
2809
2810 type = REDIRECT_TYPE_PREFIX;
2811 cur_arg++;
2812 destination = args[cur_arg];
2813 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002814 else if (!strcmp(args[cur_arg], "set-cookie")) {
2815 if (!*args[cur_arg + 1]) {
2816 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2817 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002820 }
2821
2822 cur_arg++;
2823 cookie = args[cur_arg];
2824 cookie_set = 1;
2825 }
2826 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2827 if (!*args[cur_arg + 1]) {
2828 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2829 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002832 }
2833
2834 cur_arg++;
2835 cookie = args[cur_arg];
2836 cookie_set = 0;
2837 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002838 else if (!strcmp(args[cur_arg],"code")) {
2839 if (!*args[cur_arg + 1]) {
2840 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2841 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002844 }
2845 cur_arg++;
2846 code = atol(args[cur_arg]);
2847 if (code < 301 || code > 303) {
2848 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2849 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002852 }
2853 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002854 else if (!strcmp(args[cur_arg],"drop-query")) {
2855 flags |= REDIRECT_FLAG_DROP_QS;
2856 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002857 else if (!strcmp(args[cur_arg],"append-slash")) {
2858 flags |= REDIRECT_FLAG_APPEND_SLASH;
2859 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002860 else if (strcmp(args[cur_arg], "if") == 0 ||
2861 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002862 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002863 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002864 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2865 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
2868 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002869 break;
2870 }
2871 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002872 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 +02002873 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002876 }
2877 cur_arg++;
2878 }
2879
2880 if (type == REDIRECT_TYPE_NONE) {
2881 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2882 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002885 }
2886
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002887 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2888 rule->cond = cond;
2889 rule->rdr_str = strdup(destination);
2890 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002891 if (cookie) {
2892 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002893 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002894 */
2895 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002896 if (cookie_set) {
2897 rule->cookie_str = malloc(rule->cookie_len + 10);
2898 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2899 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2900 rule->cookie_len += 9;
2901 } else {
2902 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002903 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002904 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2905 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002906 }
2907 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002908 rule->type = type;
2909 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002910 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002911 LIST_INIT(&rule->list);
2912 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002913 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2914 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002915 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002916 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002917 struct switching_rule *rule;
2918
Willy Tarreaub099aca2008-10-12 17:26:37 +02002919 if (curproxy == &defproxy) {
2920 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002923 }
2924
Willy Tarreau55ea7572007-06-17 19:56:27 +02002925 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002927
2928 if (*(args[1]) == 0) {
2929 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002932 }
2933
Willy Tarreauef6494c2010-01-28 17:12:36 +01002934 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002935 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2936 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002937 err_code |= ERR_ALERT | ERR_FATAL;
2938 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002939 }
2940
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002941 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2942 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2943 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002946 }
2947
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002948 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002949
Willy Tarreau55ea7572007-06-17 19:56:27 +02002950 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2951 rule->cond = cond;
2952 rule->be.name = strdup(args[1]);
2953 LIST_INIT(&rule->list);
2954 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2955 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002956 else if (strcmp(args[0], "use-server") == 0) {
2957 struct server_rule *rule;
2958
2959 if (curproxy == &defproxy) {
2960 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
2964
2965 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2966 err_code |= ERR_WARN;
2967
2968 if (*(args[1]) == 0) {
2969 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
2973
2974 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2975 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2976 file, linenum, args[0]);
2977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
2979 }
2980
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002981 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2982 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2983 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
2986 }
2987
2988 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2989
2990 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2991 rule->cond = cond;
2992 rule->srv.name = strdup(args[1]);
2993 LIST_INIT(&rule->list);
2994 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2995 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2996 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002997 else if ((!strcmp(args[0], "force-persist")) ||
2998 (!strcmp(args[0], "ignore-persist"))) {
2999 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003000
3001 if (curproxy == &defproxy) {
3002 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
3006
3007 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3008 err_code |= ERR_WARN;
3009
Willy Tarreauef6494c2010-01-28 17:12:36 +01003010 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003011 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3012 file, linenum, args[0]);
3013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
3015 }
3016
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003017 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3018 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3019 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
3022 }
3023
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003024 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003025
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003026 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003027 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003028 if (!strcmp(args[0], "force-persist")) {
3029 rule->type = PERSIST_TYPE_FORCE;
3030 } else {
3031 rule->type = PERSIST_TYPE_IGNORE;
3032 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003033 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003034 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003035 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003036 else if (!strcmp(args[0], "stick-table")) {
3037 int myidx = 1;
3038
Emeric Brun32da3c42010-09-23 18:39:19 +02003039 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003040 curproxy->table.type = (unsigned int)-1;
3041 while (*args[myidx]) {
3042 const char *err;
3043
3044 if (strcmp(args[myidx], "size") == 0) {
3045 myidx++;
3046 if (!*(args[myidx])) {
3047 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3048 file, linenum, args[myidx-1]);
3049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
3051 }
3052 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3053 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3054 file, linenum, *err, args[myidx-1]);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003058 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003059 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003060 else if (strcmp(args[myidx], "peers") == 0) {
3061 myidx++;
3062 if (!*(args[myidx])) {
3063 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3064 file, linenum, args[myidx-1]);
3065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
3067 }
3068 curproxy->table.peers.name = strdup(args[myidx++]);
3069 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003070 else if (strcmp(args[myidx], "expire") == 0) {
3071 myidx++;
3072 if (!*(args[myidx])) {
3073 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3074 file, linenum, args[myidx-1]);
3075 err_code |= ERR_ALERT | ERR_FATAL;
3076 goto out;
3077 }
3078 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3079 if (err) {
3080 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3081 file, linenum, *err, args[myidx-1]);
3082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
3084 }
3085 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003086 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003087 }
3088 else if (strcmp(args[myidx], "nopurge") == 0) {
3089 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003090 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003091 }
3092 else if (strcmp(args[myidx], "type") == 0) {
3093 myidx++;
3094 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3095 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3096 file, linenum, args[myidx]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003100 /* myidx already points to next arg */
3101 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003102 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003103 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003104 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003105
3106 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003107 nw = args[myidx];
3108 while (*nw) {
3109 /* the "store" keyword supports a comma-separated list */
3110 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003111 sa = NULL; /* store arg */
3112 while (*nw && *nw != ',') {
3113 if (*nw == '(') {
3114 *nw = 0;
3115 sa = ++nw;
3116 while (*nw != ')') {
3117 if (!*nw) {
3118 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3119 file, linenum, args[0], cw);
3120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
3122 }
3123 nw++;
3124 }
3125 *nw = '\0';
3126 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003127 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003128 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003129 if (*nw)
3130 *nw++ = '\0';
3131 type = stktable_get_data_type(cw);
3132 if (type < 0) {
3133 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3134 file, linenum, args[0], cw);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
Willy Tarreauac782882010-06-20 10:41:54 +02003138
3139 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3140 switch (err) {
3141 case PE_NONE: break;
3142 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003143 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3144 file, linenum, args[0], cw);
3145 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003146 break;
3147
3148 case PE_ARG_MISSING:
3149 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3150 file, linenum, args[0], cw);
3151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
3153
3154 case PE_ARG_NOT_USED:
3155 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3156 file, linenum, args[0], cw);
3157 err_code |= ERR_ALERT | ERR_FATAL;
3158 goto out;
3159
3160 default:
3161 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3162 file, linenum, args[0], cw);
3163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003165 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003166 }
3167 myidx++;
3168 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003169 else {
3170 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3171 file, linenum, args[myidx]);
3172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003174 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003175 }
3176
3177 if (!curproxy->table.size) {
3178 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3179 file, linenum);
3180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
3183
3184 if (curproxy->table.type == (unsigned int)-1) {
3185 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3186 file, linenum);
3187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
3189 }
3190 }
3191 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003192 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003193 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003194 int myidx = 0;
3195 const char *name = NULL;
3196 int flags;
3197
3198 if (curproxy == &defproxy) {
3199 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
3202 }
3203
3204 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3205 err_code |= ERR_WARN;
3206 goto out;
3207 }
3208
3209 myidx++;
3210 if ((strcmp(args[myidx], "store") == 0) ||
3211 (strcmp(args[myidx], "store-request") == 0)) {
3212 myidx++;
3213 flags = STK_IS_STORE;
3214 }
3215 else if (strcmp(args[myidx], "store-response") == 0) {
3216 myidx++;
3217 flags = STK_IS_STORE | STK_ON_RSP;
3218 }
3219 else if (strcmp(args[myidx], "match") == 0) {
3220 myidx++;
3221 flags = STK_IS_MATCH;
3222 }
3223 else if (strcmp(args[myidx], "on") == 0) {
3224 myidx++;
3225 flags = STK_IS_MATCH | STK_IS_STORE;
3226 }
3227 else {
3228 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3229 err_code |= ERR_ALERT | ERR_FATAL;
3230 goto out;
3231 }
3232
3233 if (*(args[myidx]) == 0) {
3234 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
3237 }
3238
David du Colombier7af46052012-05-16 14:16:48 +02003239 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003240 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003241 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
3244 }
3245
3246 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003247 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003248 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3249 file, linenum, args[0], expr->fetch->kw);
3250 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003251 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003252 goto out;
3253 }
3254 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003255 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003256 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3257 file, linenum, args[0], expr->fetch->kw);
3258 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003259 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003260 goto out;
3261 }
3262 }
3263
3264 if (strcmp(args[myidx], "table") == 0) {
3265 myidx++;
3266 name = args[myidx++];
3267 }
3268
Willy Tarreauef6494c2010-01-28 17:12:36 +01003269 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003270 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3271 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3272 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003273 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003274 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003275 goto out;
3276 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003277 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003278 else if (*(args[myidx])) {
3279 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3280 file, linenum, args[0], args[myidx]);
3281 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003282 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003283 goto out;
3284 }
Emeric Brun97679e72010-09-23 17:56:44 +02003285 if (flags & STK_ON_RSP)
3286 err_code |= warnif_cond_requires_req(cond, file, linenum);
3287 else
3288 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003289
Emeric Brunb982a3d2010-01-04 15:45:53 +01003290 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3291 rule->cond = cond;
3292 rule->expr = expr;
3293 rule->flags = flags;
3294 rule->table.name = name ? strdup(name) : NULL;
3295 LIST_INIT(&rule->list);
3296 if (flags & STK_ON_RSP)
3297 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3298 else
3299 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003302 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003303 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003304
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3306 curproxy->uri_auth = NULL; /* we must detach from the default config */
3307
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003308 if (!*args[1]) {
3309 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003310 } else if (!strcmp(args[1], "admin")) {
3311 struct stats_admin_rule *rule;
3312
3313 if (curproxy == &defproxy) {
3314 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3315 err_code |= ERR_ALERT | ERR_FATAL;
3316 goto out;
3317 }
3318
3319 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3320 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3321 err_code |= ERR_ALERT | ERR_ABORT;
3322 goto out;
3323 }
3324
3325 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3326 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3327 file, linenum, args[0], args[1]);
3328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
3330 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003331 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3332 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3333 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
3336 }
3337
3338 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3339
3340 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3341 rule->cond = cond;
3342 LIST_INIT(&rule->list);
3343 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 } else if (!strcmp(args[1], "uri")) {
3345 if (*(args[2]) == 0) {
3346 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3350 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003351 err_code |= ERR_ALERT | ERR_ABORT;
3352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 }
3354 } else if (!strcmp(args[1], "realm")) {
3355 if (*(args[2]) == 0) {
3356 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3360 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_ABORT;
3362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003364 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003365 unsigned interval;
3366
3367 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3368 if (err) {
3369 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3370 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003373 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3374 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003375 err_code |= ERR_ALERT | ERR_ABORT;
3376 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003377 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003378 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003379 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003380
3381 if (curproxy == &defproxy) {
3382 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
3385 }
3386
3387 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3388 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3389 err_code |= ERR_ALERT | ERR_ABORT;
3390 goto out;
3391 }
3392
Willy Tarreauff011f22011-01-06 17:51:27 +01003393 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3394 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003395 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3396 file, linenum, args[0]);
3397 err_code |= ERR_WARN;
3398 }
3399
Willy Tarreauff011f22011-01-06 17:51:27 +01003400 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003401
Willy Tarreauff011f22011-01-06 17:51:27 +01003402 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003403 err_code |= ERR_ALERT | ERR_ABORT;
3404 goto out;
3405 }
3406
Willy Tarreauff011f22011-01-06 17:51:27 +01003407 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3408 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003409
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 } else if (!strcmp(args[1], "auth")) {
3411 if (*(args[2]) == 0) {
3412 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003413 err_code |= ERR_ALERT | ERR_FATAL;
3414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3416 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003417 err_code |= ERR_ALERT | ERR_ABORT;
3418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 }
3420 } else if (!strcmp(args[1], "scope")) {
3421 if (*(args[2]) == 0) {
3422 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3426 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003427 err_code |= ERR_ALERT | ERR_ABORT;
3428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 }
3430 } else if (!strcmp(args[1], "enable")) {
3431 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3432 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_ABORT;
3434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003436 } else if (!strcmp(args[1], "hide-version")) {
3437 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3438 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003439 err_code |= ERR_ALERT | ERR_ABORT;
3440 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003441 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003442 } else if (!strcmp(args[1], "show-legends")) {
3443 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3444 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3445 err_code |= ERR_ALERT | ERR_ABORT;
3446 goto out;
3447 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003448 } else if (!strcmp(args[1], "show-node")) {
3449
3450 if (*args[2]) {
3451 int i;
3452 char c;
3453
3454 for (i=0; args[2][i]; i++) {
3455 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003456 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3457 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003458 break;
3459 }
3460
3461 if (!i || args[2][i]) {
3462 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3463 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3464 file, linenum, args[0], args[1]);
3465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
3467 }
3468 }
3469
3470 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3471 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3472 err_code |= ERR_ALERT | ERR_ABORT;
3473 goto out;
3474 }
3475 } else if (!strcmp(args[1], "show-desc")) {
3476 char *desc = NULL;
3477
3478 if (*args[2]) {
3479 int i, len=0;
3480 char *d;
3481
3482 for(i=2; *args[i]; i++)
3483 len += strlen(args[i])+1;
3484
3485 desc = d = (char *)calloc(1, len);
3486
3487 d += sprintf(d, "%s", args[2]);
3488 for(i=3; *args[i]; i++)
3489 d += sprintf(d, " %s", args[i]);
3490 }
3491
3492 if (!*args[2] && !global.desc)
3493 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3494 file, linenum, args[1]);
3495 else {
3496 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3497 free(desc);
3498 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3499 err_code |= ERR_ALERT | ERR_ABORT;
3500 goto out;
3501 }
3502 free(desc);
3503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003505stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003506 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 +01003507 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 }
3511 }
3512 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003513 int optnum;
3514
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003515 if (*(args[1]) == '\0') {
3516 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3517 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003521
3522 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3523 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003524 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3525 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3526 file, linenum, cfg_opts[optnum].name);
3527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
3529 }
Willy Tarreau93893792009-07-23 13:19:11 +02003530 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3531 err_code |= ERR_WARN;
3532 goto out;
3533 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003534
Willy Tarreau3842f002009-06-14 11:39:52 +02003535 curproxy->no_options &= ~cfg_opts[optnum].val;
3536 curproxy->options &= ~cfg_opts[optnum].val;
3537
3538 switch (kwm) {
3539 case KWM_STD:
3540 curproxy->options |= cfg_opts[optnum].val;
3541 break;
3542 case KWM_NO:
3543 curproxy->no_options |= cfg_opts[optnum].val;
3544 break;
3545 case KWM_DEF: /* already cleared */
3546 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003547 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003548
Willy Tarreau93893792009-07-23 13:19:11 +02003549 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003550 }
3551 }
3552
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003553 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3554 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003555 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3556 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3557 file, linenum, cfg_opts2[optnum].name);
3558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
3560 }
Willy Tarreau93893792009-07-23 13:19:11 +02003561 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3562 err_code |= ERR_WARN;
3563 goto out;
3564 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003565
Willy Tarreau3842f002009-06-14 11:39:52 +02003566 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3567 curproxy->options2 &= ~cfg_opts2[optnum].val;
3568
3569 switch (kwm) {
3570 case KWM_STD:
3571 curproxy->options2 |= cfg_opts2[optnum].val;
3572 break;
3573 case KWM_NO:
3574 curproxy->no_options2 |= cfg_opts2[optnum].val;
3575 break;
3576 case KWM_DEF: /* already cleared */
3577 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003578 }
Willy Tarreau93893792009-07-23 13:19:11 +02003579 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003580 }
3581 }
3582
Willy Tarreau3842f002009-06-14 11:39:52 +02003583 if (kwm != KWM_STD) {
3584 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003585 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003588 }
3589
Emeric Brun3a058f32009-06-30 18:26:00 +02003590 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003591 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003592 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003593 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003594 if (*(args[2]) != '\0') {
3595 if (!strcmp(args[2], "clf")) {
3596 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003597 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003598 } else {
3599 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003602 }
3603 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003604 if (curproxy->logformat_string != default_http_log_format &&
3605 curproxy->logformat_string != default_tcp_log_format &&
3606 curproxy->logformat_string != clf_http_log_format)
3607 free(curproxy->logformat_string);
3608 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003609 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003610 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003612 if (curproxy->logformat_string != default_http_log_format &&
3613 curproxy->logformat_string != default_tcp_log_format &&
3614 curproxy->logformat_string != clf_http_log_format)
3615 free(curproxy->logformat_string);
3616 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003618 else if (!strcmp(args[1], "tcpka")) {
3619 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003620 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003621 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003622
3623 if (curproxy->cap & PR_CAP_FE)
3624 curproxy->options |= PR_O_TCP_CLI_KA;
3625 if (curproxy->cap & PR_CAP_BE)
3626 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 }
3628 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003629 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_WARN;
3631
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003633 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003634 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003635 curproxy->options2 &= ~PR_O2_CHK_ANY;
3636 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 if (!*args[2]) { /* no argument */
3638 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3639 curproxy->check_len = strlen(DEF_CHECK_REQ);
3640 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003641 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 curproxy->check_req = (char *)malloc(reqlen);
3643 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003644 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003646 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 if (*args[4])
3648 reqlen += strlen(args[4]);
3649 else
3650 reqlen += strlen("HTTP/1.0");
3651
3652 curproxy->check_req = (char *)malloc(reqlen);
3653 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003654 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003656 }
3657 else if (!strcmp(args[1], "ssl-hello-chk")) {
3658 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003659 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003661
Willy Tarreaua534fea2008-08-03 12:19:50 +02003662 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003663 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003664 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003665 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003666 }
Willy Tarreau23677902007-05-08 23:50:35 +02003667 else if (!strcmp(args[1], "smtpchk")) {
3668 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003669 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003670 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003671 curproxy->options2 &= ~PR_O2_CHK_ANY;
3672 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003673
3674 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3675 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3676 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3677 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3678 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3679 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3680 curproxy->check_req = (char *)malloc(reqlen);
3681 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3682 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3683 } else {
3684 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3685 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3686 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3687 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3688 }
3689 }
3690 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003691 else if (!strcmp(args[1], "pgsql-check")) {
3692 /* use PostgreSQL request to check servers' health */
3693 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3694 err_code |= ERR_WARN;
3695
3696 free(curproxy->check_req);
3697 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003698 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003699 curproxy->options2 |= PR_O2_PGSQL_CHK;
3700
3701 if (*(args[2])) {
3702 int cur_arg = 2;
3703
3704 while (*(args[cur_arg])) {
3705 if (strcmp(args[cur_arg], "user") == 0) {
3706 char * packet;
3707 uint32_t packet_len;
3708 uint32_t pv;
3709
3710 /* suboption header - needs additional argument for it */
3711 if (*(args[cur_arg+1]) == 0) {
3712 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3713 file, linenum, args[0], args[1], args[cur_arg]);
3714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
3716 }
3717
3718 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3719 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3720 pv = htonl(0x30000); /* protocol version 3.0 */
3721
3722 packet = (char*) calloc(1, packet_len);
3723
3724 memcpy(packet + 4, &pv, 4);
3725
3726 /* copy "user" */
3727 memcpy(packet + 8, "user", 4);
3728
3729 /* copy username */
3730 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3731
3732 free(curproxy->check_req);
3733 curproxy->check_req = packet;
3734 curproxy->check_len = packet_len;
3735
3736 packet_len = htonl(packet_len);
3737 memcpy(packet, &packet_len, 4);
3738 cur_arg += 2;
3739 } else {
3740 /* unknown suboption - catchall */
3741 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3742 file, linenum, args[0], args[1]);
3743 err_code |= ERR_ALERT | ERR_FATAL;
3744 goto out;
3745 }
3746 } /* end while loop */
3747 }
3748 }
3749
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003750 else if (!strcmp(args[1], "redis-check")) {
3751 /* use REDIS PING request to check servers' health */
3752 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3753 err_code |= ERR_WARN;
3754
3755 free(curproxy->check_req);
3756 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003757 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003758 curproxy->options2 |= PR_O2_REDIS_CHK;
3759
3760 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3761 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3762 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3763 }
3764
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003765 else if (!strcmp(args[1], "mysql-check")) {
3766 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003767 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3768 err_code |= ERR_WARN;
3769
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003770 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003771 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003772 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003773 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003774
3775 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3776 * const char mysql40_client_auth_pkt[] = {
3777 * "\x0e\x00\x00" // packet length
3778 * "\x01" // packet number
3779 * "\x00\x00" // client capabilities
3780 * "\x00\x00\x01" // max packet
3781 * "haproxy\x00" // username (null terminated string)
3782 * "\x00" // filler (always 0x00)
3783 * "\x01\x00\x00" // packet length
3784 * "\x00" // packet number
3785 * "\x01" // COM_QUIT command
3786 * };
3787 */
3788
3789 if (*(args[2])) {
3790 int cur_arg = 2;
3791
3792 while (*(args[cur_arg])) {
3793 if (strcmp(args[cur_arg], "user") == 0) {
3794 char *mysqluser;
3795 int packetlen, reqlen, userlen;
3796
3797 /* suboption header - needs additional argument for it */
3798 if (*(args[cur_arg+1]) == 0) {
3799 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3800 file, linenum, args[0], args[1], args[cur_arg]);
3801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
3803 }
3804 mysqluser = args[cur_arg + 1];
3805 userlen = strlen(mysqluser);
3806 packetlen = userlen + 7;
3807 reqlen = packetlen + 9;
3808
3809 free(curproxy->check_req);
3810 curproxy->check_req = (char *)calloc(1, reqlen);
3811 curproxy->check_len = reqlen;
3812
3813 snprintf(curproxy->check_req, 4, "%c%c%c",
3814 ((unsigned char) packetlen & 0xff),
3815 ((unsigned char) (packetlen >> 8) & 0xff),
3816 ((unsigned char) (packetlen >> 16) & 0xff));
3817
3818 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003819 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003820 curproxy->check_req[8] = 1;
3821 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3822 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3823 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3824 cur_arg += 2;
3825 } else {
3826 /* unknown suboption - catchall */
3827 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3828 file, linenum, args[0], args[1]);
3829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832 } /* end while loop */
3833 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003834 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003835 else if (!strcmp(args[1], "ldap-check")) {
3836 /* use LDAP request to check servers' health */
3837 free(curproxy->check_req);
3838 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003839 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003840 curproxy->options2 |= PR_O2_LDAP_CHK;
3841
3842 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3843 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3844 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3845 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003846 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003847 int cur_arg;
3848
3849 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3850 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003851 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003852
Willy Tarreau87cf5142011-08-19 22:57:24 +02003853 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003854
3855 free(curproxy->fwdfor_hdr_name);
3856 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3857 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3858
3859 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3860 cur_arg = 2;
3861 while (*(args[cur_arg])) {
3862 if (!strcmp(args[cur_arg], "except")) {
3863 /* suboption except - needs additional argument for it */
3864 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3865 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3866 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003869 }
3870 /* flush useless bits */
3871 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003872 cur_arg += 2;
3873 } else if (!strcmp(args[cur_arg], "header")) {
3874 /* suboption header - needs additional argument for it */
3875 if (*(args[cur_arg+1]) == 0) {
3876 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3877 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003880 }
3881 free(curproxy->fwdfor_hdr_name);
3882 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3883 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3884 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003885 } else if (!strcmp(args[cur_arg], "if-none")) {
3886 curproxy->options &= ~PR_O_FF_ALWAYS;
3887 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003888 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003889 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003890 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003891 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003894 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003895 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003896 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003897 else if (!strcmp(args[1], "originalto")) {
3898 int cur_arg;
3899
3900 /* insert x-original-to field, but not for the IP address listed as an except.
3901 * set default options (ie: bitfield, header name, etc)
3902 */
3903
3904 curproxy->options |= PR_O_ORGTO;
3905
3906 free(curproxy->orgto_hdr_name);
3907 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3908 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3909
Willy Tarreau87cf5142011-08-19 22:57:24 +02003910 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003911 cur_arg = 2;
3912 while (*(args[cur_arg])) {
3913 if (!strcmp(args[cur_arg], "except")) {
3914 /* suboption except - needs additional argument for it */
3915 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3916 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3917 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003920 }
3921 /* flush useless bits */
3922 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3923 cur_arg += 2;
3924 } else if (!strcmp(args[cur_arg], "header")) {
3925 /* suboption header - needs additional argument for it */
3926 if (*(args[cur_arg+1]) == 0) {
3927 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3928 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003931 }
3932 free(curproxy->orgto_hdr_name);
3933 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3934 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3935 cur_arg += 2;
3936 } else {
3937 /* unknown suboption - catchall */
3938 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3939 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003942 }
3943 } /* end while loop */
3944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 else {
3946 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 }
Willy Tarreau93893792009-07-23 13:19:11 +02003950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003952 else if (!strcmp(args[0], "default_backend")) {
3953 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003954 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003955
3956 if (*(args[1]) == 0) {
3957 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003960 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003961 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003962 curproxy->defbe.name = strdup(args[1]);
3963 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003965 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
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003968 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3969 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971 /* enable reconnections to dispatch */
3972 curproxy->options |= PR_O_REDISP;
3973 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003974 else if (!strcmp(args[0], "http-check")) {
3975 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003976 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003977
3978 if (strcmp(args[1], "disable-on-404") == 0) {
3979 /* enable a graceful server shutdown on an HTTP 404 response */
3980 curproxy->options |= PR_O_DISABLE404;
3981 }
Willy Tarreauef781042010-01-27 11:53:01 +01003982 else if (strcmp(args[1], "send-state") == 0) {
3983 /* enable emission of the apparent state of a server in HTTP checks */
3984 curproxy->options2 |= PR_O2_CHK_SNDST;
3985 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003986 else if (strcmp(args[1], "expect") == 0) {
3987 const char *ptr_arg;
3988 int cur_arg;
3989
3990 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3991 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
3995
3996 cur_arg = 2;
3997 /* consider exclamation marks, sole or at the beginning of a word */
3998 while (*(ptr_arg = args[cur_arg])) {
3999 while (*ptr_arg == '!') {
4000 curproxy->options2 ^= PR_O2_EXP_INV;
4001 ptr_arg++;
4002 }
4003 if (*ptr_arg)
4004 break;
4005 cur_arg++;
4006 }
4007 /* now ptr_arg points to the beginning of a word past any possible
4008 * exclamation mark, and cur_arg is the argument which holds this word.
4009 */
4010 if (strcmp(ptr_arg, "status") == 0) {
4011 if (!*(args[cur_arg + 1])) {
4012 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4013 file, linenum, args[0], args[1], ptr_arg);
4014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
4016 }
4017 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004018 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004019 curproxy->expect_str = strdup(args[cur_arg + 1]);
4020 }
4021 else if (strcmp(ptr_arg, "string") == 0) {
4022 if (!*(args[cur_arg + 1])) {
4023 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4024 file, linenum, args[0], args[1], ptr_arg);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
4028 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004029 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004030 curproxy->expect_str = strdup(args[cur_arg + 1]);
4031 }
4032 else if (strcmp(ptr_arg, "rstatus") == 0) {
4033 if (!*(args[cur_arg + 1])) {
4034 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4035 file, linenum, args[0], args[1], ptr_arg);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
4038 }
4039 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004040 free(curproxy->expect_str);
4041 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4042 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004043 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4044 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4045 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4046 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
4049 }
4050 }
4051 else if (strcmp(ptr_arg, "rstring") == 0) {
4052 if (!*(args[cur_arg + 1])) {
4053 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4054 file, linenum, args[0], args[1], ptr_arg);
4055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
4057 }
4058 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004059 free(curproxy->expect_str);
4060 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4061 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004062 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4063 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4064 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4065 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069 }
4070 else {
4071 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4072 file, linenum, args[0], args[1], ptr_arg);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004077 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004078 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 +02004079 err_code |= ERR_ALERT | ERR_FATAL;
4080 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004081 }
4082 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004083 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004084 if (curproxy == &defproxy) {
4085 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004088 }
4089
Willy Tarreaub80c2302007-11-30 20:51:32 +01004090 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004091 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004092
4093 if (strcmp(args[1], "fail") == 0) {
4094 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004095 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004096 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4097 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004100 }
4101
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004102 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4103 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4104 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004107 }
4108 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4109 }
4110 else {
4111 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004114 }
4115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004116#ifdef TPROXY
4117 else if (!strcmp(args[0], "transparent")) {
4118 /* enable transparent proxy connections */
4119 curproxy->options |= PR_O_TRANSP;
4120 }
4121#endif
4122 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004123 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004125
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 if (*(args[1]) == 0) {
4127 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004130 }
4131 curproxy->maxconn = atol(args[1]);
4132 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004133 else if (!strcmp(args[0], "backlog")) { /* backlog */
4134 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004135 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004136
4137 if (*(args[1]) == 0) {
4138 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004141 }
4142 curproxy->backlog = atol(args[1]);
4143 }
Willy Tarreau86034312006-12-29 00:10:33 +01004144 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004145 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004146 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004147
Willy Tarreau86034312006-12-29 00:10:33 +01004148 if (*(args[1]) == 0) {
4149 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004150 err_code |= ERR_ALERT | ERR_FATAL;
4151 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004152 }
4153 curproxy->fullconn = atol(args[1]);
4154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4156 if (*(args[1]) == 0) {
4157 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004161 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4162 if (err) {
4163 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4164 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004167 }
4168 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 }
4170 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004171 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004172 if (curproxy == &defproxy) {
4173 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004177 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004178 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004179
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 if (strchr(args[1], ':') == NULL) {
4181 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004184 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004185 sk = str2sa(args[1]);
4186 if (!sk) {
4187 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
4190 }
4191 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004192 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004193 }
4194 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004195 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004196 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004197
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004198 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4199 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004203 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004204 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4205 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4206 err_code |= ERR_WARN;
4207
4208 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4209 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4210 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4211 }
4212 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4213 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4214 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4215 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004216 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4217 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4218 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4219 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004220 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004221 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224 }
4225 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004226 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004228 char *rport, *raddr;
4229 short realport = 0;
4230 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004232 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004236 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004237 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004238 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004239
4240 if (!*args[2]) {
4241 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4242 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004245 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004246
4247 err = invalid_char(args[1]);
4248 if (err) {
4249 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4250 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004253 }
4254
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004255 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004256 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004257
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004258 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4259 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4260 err_code |= ERR_ALERT | ERR_ABORT;
4261 goto out;
4262 }
4263
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004264 /* the servers are linked backwards first */
4265 newsrv->next = curproxy->srv;
4266 curproxy->srv = newsrv;
4267 newsrv->proxy = curproxy;
4268 newsrv->conf.file = file;
4269 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004270
Simon Hormanaf514952011-06-21 14:34:57 +09004271 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004272 LIST_INIT(&newsrv->pendconns);
4273 do_check = 0;
4274 newsrv->state = SRV_RUNNING; /* early server setup */
4275 newsrv->last_change = now.tv_sec;
4276 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004277
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004278 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004279 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004280 * - IP: => port=+0, relative
4281 * - IP:N => port=N, absolute
4282 * - IP:+N => port=+N, relative
4283 * - IP:-N => port=-N, relative
4284 */
4285 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004286 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004287 if (rport) {
4288 *rport++ = 0;
4289 realport = atol(rport);
4290 if (!isdigit((unsigned char)*rport))
4291 newsrv->state |= SRV_MAPPORTS;
4292 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004293 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004294
Willy Tarreaufab5a432011-03-04 15:31:53 +01004295 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004296 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004297 if (!sk) {
4298 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004303 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004304 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004305
4306 if (!sk) {
4307 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4308 file, linenum, newsrv->addr.ss_family, args[2]);
4309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
4311 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004312 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004313
4314 newsrv->check_port = curproxy->defsrv.check_port;
4315 newsrv->inter = curproxy->defsrv.inter;
4316 newsrv->fastinter = curproxy->defsrv.fastinter;
4317 newsrv->downinter = curproxy->defsrv.downinter;
4318 newsrv->rise = curproxy->defsrv.rise;
4319 newsrv->fall = curproxy->defsrv.fall;
4320 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4321 newsrv->minconn = curproxy->defsrv.minconn;
4322 newsrv->maxconn = curproxy->defsrv.maxconn;
4323 newsrv->slowstart = curproxy->defsrv.slowstart;
4324 newsrv->onerror = curproxy->defsrv.onerror;
4325 newsrv->consecutive_errors_limit
4326 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004327#ifdef OPENSSL
4328 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4329#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004330 newsrv->uweight = newsrv->iweight
4331 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004333 newsrv->curfd = -1; /* no health-check in progress */
4334 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004335
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004336 cur_arg = 3;
4337 } else {
4338 newsrv = &curproxy->defsrv;
4339 cur_arg = 1;
4340 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004341
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004343 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004344 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004345
4346 if (!*args[cur_arg + 1]) {
4347 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4348 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004351 }
4352
4353 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004354 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004355
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004356 if (newsrv->puid <= 0) {
4357 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004358 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004361 }
4362
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004363 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4364 if (node) {
4365 struct server *target = container_of(node, struct server, conf.id);
4366 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4367 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004372 cur_arg += 2;
4373 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004374 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004375 newsrv->cookie = strdup(args[cur_arg + 1]);
4376 newsrv->cklen = strlen(args[cur_arg + 1]);
4377 cur_arg += 2;
4378 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004379 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004380 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4381 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4382 cur_arg += 2;
4383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004384 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004385 if (!*args[cur_arg + 1]) {
4386 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4387 file, linenum, args[cur_arg]);
4388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
4390 }
4391
Willy Tarreaubaaee002006-06-26 02:48:02 +02004392 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004393 if (newsrv->rise <= 0) {
4394 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4395 file, linenum, args[cur_arg]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
4399
Willy Tarreau96839092010-03-29 10:02:24 +02004400 if (newsrv->health)
4401 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 cur_arg += 2;
4403 }
4404 else if (!strcmp(args[cur_arg], "fall")) {
4405 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004406
4407 if (!*args[cur_arg + 1]) {
4408 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4409 file, linenum, args[cur_arg]);
4410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
4412 }
4413
4414 if (newsrv->fall <= 0) {
4415 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4416 file, linenum, args[cur_arg]);
4417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
4419 }
4420
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 cur_arg += 2;
4422 }
4423 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004424 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4425 if (err) {
4426 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4427 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004430 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004431 if (val <= 0) {
4432 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4433 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004434 err_code |= ERR_ALERT | ERR_FATAL;
4435 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004436 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004437 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004438 cur_arg += 2;
4439 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004440 else if (!strcmp(args[cur_arg], "fastinter")) {
4441 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4442 if (err) {
4443 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4444 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004447 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004448 if (val <= 0) {
4449 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4450 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004453 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004454 newsrv->fastinter = val;
4455 cur_arg += 2;
4456 }
4457 else if (!strcmp(args[cur_arg], "downinter")) {
4458 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4459 if (err) {
4460 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4461 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004462 err_code |= ERR_ALERT | ERR_FATAL;
4463 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004464 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004465 if (val <= 0) {
4466 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4467 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004470 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004471 newsrv->downinter = val;
4472 cur_arg += 2;
4473 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004474 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004475 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004476 if (!sk) {
4477 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4478 err_code |= ERR_ALERT | ERR_FATAL;
4479 goto out;
4480 }
4481 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004482 cur_arg += 2;
4483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 else if (!strcmp(args[cur_arg], "port")) {
4485 newsrv->check_port = atol(args[cur_arg + 1]);
4486 cur_arg += 2;
4487 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004488 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 newsrv->state |= SRV_BACKUP;
4490 cur_arg ++;
4491 }
Simon Hormanfa461682011-06-25 09:39:49 +09004492 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4493 newsrv->state |= SRV_NON_STICK;
4494 cur_arg ++;
4495 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004496 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4497 newsrv->state |= SRV_SEND_PROXY;
4498 cur_arg ++;
4499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 else if (!strcmp(args[cur_arg], "weight")) {
4501 int w;
4502 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004503 if (w < 0 || w > 256) {
4504 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004509 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 cur_arg += 2;
4511 }
4512 else if (!strcmp(args[cur_arg], "minconn")) {
4513 newsrv->minconn = atol(args[cur_arg + 1]);
4514 cur_arg += 2;
4515 }
4516 else if (!strcmp(args[cur_arg], "maxconn")) {
4517 newsrv->maxconn = atol(args[cur_arg + 1]);
4518 cur_arg += 2;
4519 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004520 else if (!strcmp(args[cur_arg], "maxqueue")) {
4521 newsrv->maxqueue = atol(args[cur_arg + 1]);
4522 cur_arg += 2;
4523 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004524 else if (!strcmp(args[cur_arg], "slowstart")) {
4525 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004526 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004527 if (err) {
4528 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4529 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004532 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004533 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004534 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4535 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004538 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004539 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004540 cur_arg += 2;
4541 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004542 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004543
4544 if (!*args[cur_arg + 1]) {
4545 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4546 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004549 }
4550
4551 newsrv->trackit = strdup(args[cur_arg + 1]);
4552
4553 cur_arg += 2;
4554 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004555 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004556 global.maxsock++;
4557 do_check = 1;
4558 cur_arg += 1;
4559 }
Willy Tarreau96839092010-03-29 10:02:24 +02004560 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4561 newsrv->state |= SRV_MAINTAIN;
4562 newsrv->state &= ~SRV_RUNNING;
4563 newsrv->health = 0;
4564 cur_arg += 1;
4565 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004566 else if (!strcmp(args[cur_arg], "ssl")) {
4567#ifdef USE_OPENSSL
4568 newsrv->use_ssl = 1;
4569 cur_arg += 1;
4570#else /* USE_OPENSSL */
4571 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4572 file, linenum, args[cur_arg]);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575#endif /* USE_OPENSSL */
4576 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004577 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4578#ifdef USE_OPENSSL
4579 if (!*args[cur_arg + 1]) {
4580 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4581 file, linenum, args[0], args[cur_arg]);
4582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
4584 }
4585
4586 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4587
4588 cur_arg += 2;
4589 continue;
4590#else
4591 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4592 file, linenum, args[0], args[cur_arg]);
4593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
4595#endif
4596 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004597 else if (!strcmp(args[cur_arg], "nosslv3")) {
4598#ifdef USE_OPENSSL
4599 newsrv->ssl_ctx.nosslv3 = 1;
4600 cur_arg += 1;
4601#else /* USE_OPENSSL */
4602 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4603 file, linenum, args[cur_arg]);
4604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
4606#endif /* USE_OPENSSL */
4607 }
4608 else if (!strcmp(args[cur_arg], "notlsv1")) {
4609#ifdef USE_OPENSSL
4610 newsrv->ssl_ctx.notlsv1 = 1;
4611 cur_arg += 1;
4612#else /* USE_OPENSSL */
4613 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4614 file, linenum, args[cur_arg]);
4615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
4617#endif /* USE_OPENSSL */
4618 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004619 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004620 if (!strcmp(args[cur_arg + 1], "none"))
4621 newsrv->observe = HANA_OBS_NONE;
4622 else if (!strcmp(args[cur_arg + 1], "layer4"))
4623 newsrv->observe = HANA_OBS_LAYER4;
4624 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4625 if (curproxy->mode != PR_MODE_HTTP) {
4626 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4627 file, linenum, args[cur_arg + 1]);
4628 err_code |= ERR_ALERT;
4629 }
4630 newsrv->observe = HANA_OBS_LAYER7;
4631 }
4632 else {
4633 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004634 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004635 file, linenum, args[cur_arg], args[cur_arg + 1]);
4636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
4638 }
4639
4640 cur_arg += 2;
4641 }
4642 else if (!strcmp(args[cur_arg], "on-error")) {
4643 if (!strcmp(args[cur_arg + 1], "fastinter"))
4644 newsrv->onerror = HANA_ONERR_FASTINTER;
4645 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4646 newsrv->onerror = HANA_ONERR_FAILCHK;
4647 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4648 newsrv->onerror = HANA_ONERR_SUDDTH;
4649 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4650 newsrv->onerror = HANA_ONERR_MARKDWN;
4651 else {
4652 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004653 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004654 file, linenum, args[cur_arg], args[cur_arg + 1]);
4655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
4657 }
4658
4659 cur_arg += 2;
4660 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004661 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4662 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4663 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4664 else {
4665 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4666 file, linenum, args[cur_arg], args[cur_arg + 1]);
4667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
4669 }
4670
4671 cur_arg += 2;
4672 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004673 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4674 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4675 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4676 else {
4677 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4678 file, linenum, args[cur_arg], args[cur_arg + 1]);
4679 err_code |= ERR_ALERT | ERR_FATAL;
4680 goto out;
4681 }
4682
4683 cur_arg += 2;
4684 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004685 else if (!strcmp(args[cur_arg], "error-limit")) {
4686 if (!*args[cur_arg + 1]) {
4687 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4688 file, linenum, args[cur_arg]);
4689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
4691 }
4692
4693 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4694
4695 if (newsrv->consecutive_errors_limit <= 0) {
4696 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4697 file, linenum, args[cur_arg]);
4698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
4700 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004701 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004702 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004703 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004704 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004705 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004706
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004708#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004709 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004710 file, linenum, "source", "usesrc");
4711#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004712 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004713 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004714#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 }
4718 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004719 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4720 if (!sk) {
4721 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724 }
4725 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004726
4727 if (port_low != port_high) {
4728 int i;
4729 if (port_low <= 0 || port_low > 65535 ||
4730 port_high <= 0 || port_high > 65535 ||
4731 port_low > port_high) {
4732 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4733 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004736 }
4737 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4738 for (i = 0; i < newsrv->sport_range->size; i++)
4739 newsrv->sport_range->ports[i] = port_low + i;
4740 }
4741
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004743 while (*(args[cur_arg])) {
4744 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004745#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4746#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004747 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4748 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4749 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004750 err_code |= ERR_ALERT | ERR_FATAL;
4751 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004752 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004753#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004754 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004755 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004756 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004757 err_code |= ERR_ALERT | ERR_FATAL;
4758 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004759 }
4760 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004761 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004762 newsrv->state |= SRV_TPROXY_CLI;
4763 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004764 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004765 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004766 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4767 char *name, *end;
4768
4769 name = args[cur_arg+1] + 7;
4770 while (isspace(*name))
4771 name++;
4772
4773 end = name;
4774 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4775 end++;
4776
4777 newsrv->state &= ~SRV_TPROXY_MASK;
4778 newsrv->state |= SRV_TPROXY_DYN;
4779 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4780 newsrv->bind_hdr_len = end - name;
4781 memcpy(newsrv->bind_hdr_name, name, end - name);
4782 newsrv->bind_hdr_name[end-name] = '\0';
4783 newsrv->bind_hdr_occ = -1;
4784
4785 /* now look for an occurrence number */
4786 while (isspace(*end))
4787 end++;
4788 if (*end == ',') {
4789 end++;
4790 name = end;
4791 if (*end == '-')
4792 end++;
4793 while (isdigit(*end))
4794 end++;
4795 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4796 }
4797
4798 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4799 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4800 " occurrences values smaller than %d.\n",
4801 file, linenum, MAX_HDR_HISTORY);
4802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
4804 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004805 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004806 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004807 if (!sk) {
4808 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4809 err_code |= ERR_ALERT | ERR_FATAL;
4810 goto out;
4811 }
4812 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004813 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004814 }
4815 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004816#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004817 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004818#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004819 cur_arg += 2;
4820 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004821#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004822 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004823 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004824 err_code |= ERR_ALERT | ERR_FATAL;
4825 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004826#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4827 } /* "usesrc" */
4828
4829 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4830#ifdef SO_BINDTODEVICE
4831 if (!*args[cur_arg + 1]) {
4832 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4833 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004836 }
4837 if (newsrv->iface_name)
4838 free(newsrv->iface_name);
4839
4840 newsrv->iface_name = strdup(args[cur_arg + 1]);
4841 newsrv->iface_len = strlen(newsrv->iface_name);
4842 global.last_checks |= LSTCHK_NETADM;
4843#else
4844 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4845 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004846 err_code |= ERR_ALERT | ERR_FATAL;
4847 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004848#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004849 cur_arg += 2;
4850 continue;
4851 }
4852 /* this keyword in not an option of "source" */
4853 break;
4854 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004856 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004857 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4858 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004863 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004864 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 +01004865 file, linenum, newsrv->id);
4866 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004867 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 +01004868 file, linenum);
4869
Willy Tarreau93893792009-07-23 13:19:11 +02004870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 }
4873 }
4874
4875 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004876 if (newsrv->trackit) {
4877 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4878 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004879 err_code |= ERR_ALERT | ERR_FATAL;
4880 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004881 }
4882
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004883 /* try to get the port from check_addr if check_port not set */
4884 if (!newsrv->check_port)
4885 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004886
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4888 newsrv->check_port = realport; /* by default */
4889 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004890 /* not yet valid, because no port was set on
4891 * the server either. We'll check if we have
4892 * a known port on the first listener.
4893 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004894 struct listener *l = curproxy->listen;
4895 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4896 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004897 }
4898 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4900 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004904
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004905 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004906 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004907 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4908 err_code |= ERR_ALERT | ERR_ABORT;
4909 goto out;
4910 }
4911
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004912 /* Allocate buffer for partial check results... */
4913 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4914 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4915 err_code |= ERR_ALERT | ERR_ABORT;
4916 goto out;
4917 }
4918
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004919 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 newsrv->state |= SRV_CHECKED;
4921 }
4922
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004923 if (!defsrv) {
4924 if (newsrv->state & SRV_BACKUP)
4925 curproxy->srv_bck++;
4926 else
4927 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004928
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004929 newsrv->prev_state = newsrv->state;
4930 }
William Lallemanda73203e2012-03-12 12:48:57 +01004931 }
4932
4933 else if (strcmp(args[0], "unique-id-format") == 0) {
4934 if (!*(args[1])) {
4935 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
4938 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004939 free(curproxy->uniqueid_format_string);
4940 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004941 }
William Lallemanda73203e2012-03-12 12:48:57 +01004942
4943 else if (strcmp(args[0], "unique-id-header") == 0) {
4944 if (!*(args[1])) {
4945 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
4948 }
4949 free(curproxy->header_unique_id);
4950 curproxy->header_unique_id = strdup(args[1]);
4951 }
4952
William Lallemand723b73a2012-02-08 16:37:49 +01004953 else if (strcmp(args[0], "log-format") == 0) {
4954 if (!*(args[1])) {
4955 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
4958 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004959
4960 if (curproxy->logformat_string != default_http_log_format &&
4961 curproxy->logformat_string != default_tcp_log_format &&
4962 curproxy->logformat_string != clf_http_log_format)
4963 free(curproxy->logformat_string);
4964 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
William Lallemand723b73a2012-02-08 16:37:49 +01004966
William Lallemand0f99e342011-10-12 17:50:54 +02004967 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4968 /* delete previous herited or defined syslog servers */
4969 struct logsrv *back;
4970
4971 if (*(args[1]) != 0) {
4972 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
4975 }
4976
William Lallemand723b73a2012-02-08 16:37:49 +01004977 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4978 LIST_DEL(&tmplogsrv->list);
4979 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004980 }
4981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004983 struct logsrv *logsrv;
4984
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004986 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004987 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004988 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004989 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004990 LIST_INIT(&node->list);
4991 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4992 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
4994 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004995
4996 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997
William Lallemand0f99e342011-10-12 17:50:54 +02004998 logsrv->facility = get_log_facility(args[2]);
4999 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
5003
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 }
5005
William Lallemand0f99e342011-10-12 17:50:54 +02005006 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005008 logsrv->level = get_log_level(args[3]);
5009 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005011 err_code |= ERR_ALERT | ERR_FATAL;
5012 goto out;
5013
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 }
5015 }
5016
William Lallemand0f99e342011-10-12 17:50:54 +02005017 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005018 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005019 logsrv->minlvl = get_log_level(args[4]);
5020 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005021 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005022 err_code |= ERR_ALERT | ERR_FATAL;
5023 goto out;
5024
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005025 }
5026 }
5027
Robert Tsai81ae1952007-12-05 10:47:29 +01005028 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01005029 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005030 if (!sk) {
5031 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01005032 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
5035 }
William Lallemand0f99e342011-10-12 17:50:54 +02005036 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01005037 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005038 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01005039 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01005040 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5041 err_code |= ERR_ALERT | ERR_FATAL;
5042 goto out;
5043 }
William Lallemand0f99e342011-10-12 17:50:54 +02005044 logsrv->addr = *sk;
5045 if (!get_host_port(&logsrv->addr))
5046 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005047 }
William Lallemand0f99e342011-10-12 17:50:54 +02005048
5049 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 }
5051 else {
5052 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5053 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 }
5057 }
5058 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005059 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005060 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005061
Willy Tarreau977b8e42006-12-29 14:19:17 +01005062 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005063 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005064
Willy Tarreaubaaee002006-06-26 02:48:02 +02005065 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005066 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5067 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005071
5072 /* we must first clear any optional default setting */
5073 curproxy->options &= ~PR_O_TPXY_MASK;
5074 free(curproxy->iface_name);
5075 curproxy->iface_name = NULL;
5076 curproxy->iface_len = 0;
5077
Willy Tarreaud5191e72010-02-09 20:50:45 +01005078 sk = str2sa(args[1]);
5079 if (!sk) {
5080 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
5083 }
5084 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005086
5087 cur_arg = 2;
5088 while (*(args[cur_arg])) {
5089 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005090#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
5091#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005092 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
5093 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5094 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005095 err_code |= ERR_ALERT | ERR_FATAL;
5096 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005097 }
5098#endif
5099 if (!*args[cur_arg + 1]) {
5100 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5101 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005104 }
5105
5106 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005107 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005108 curproxy->options |= PR_O_TPXY_CLI;
5109 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005110 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005111 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005112 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5113 char *name, *end;
5114
5115 name = args[cur_arg+1] + 7;
5116 while (isspace(*name))
5117 name++;
5118
5119 end = name;
5120 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5121 end++;
5122
5123 curproxy->options &= ~PR_O_TPXY_MASK;
5124 curproxy->options |= PR_O_TPXY_DYN;
5125 curproxy->bind_hdr_name = calloc(1, end - name + 1);
5126 curproxy->bind_hdr_len = end - name;
5127 memcpy(curproxy->bind_hdr_name, name, end - name);
5128 curproxy->bind_hdr_name[end-name] = '\0';
5129 curproxy->bind_hdr_occ = -1;
5130
5131 /* now look for an occurrence number */
5132 while (isspace(*end))
5133 end++;
5134 if (*end == ',') {
5135 end++;
5136 name = end;
5137 if (*end == '-')
5138 end++;
5139 while (isdigit(*end))
5140 end++;
5141 curproxy->bind_hdr_occ = strl2ic(name, end-name);
5142 }
5143
5144 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
5145 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5146 " occurrences values smaller than %d.\n",
5147 file, linenum, MAX_HDR_HISTORY);
5148 err_code |= ERR_ALERT | ERR_FATAL;
5149 goto out;
5150 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005151 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005152 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005153 if (!sk) {
5154 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
5157 }
5158 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005159 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005160 }
5161 global.last_checks |= LSTCHK_NETADM;
5162#if !defined(CONFIG_HAP_LINUX_TPROXY)
5163 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005164#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005165#else /* no TPROXY support */
5166 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005167 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005168 err_code |= ERR_ALERT | ERR_FATAL;
5169 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005170#endif
5171 cur_arg += 2;
5172 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005173 }
5174
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005175 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5176#ifdef SO_BINDTODEVICE
5177 if (!*args[cur_arg + 1]) {
5178 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5179 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005180 err_code |= ERR_ALERT | ERR_FATAL;
5181 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005182 }
5183 if (curproxy->iface_name)
5184 free(curproxy->iface_name);
5185
5186 curproxy->iface_name = strdup(args[cur_arg + 1]);
5187 curproxy->iface_len = strlen(curproxy->iface_name);
5188 global.last_checks |= LSTCHK_NETADM;
5189#else
5190 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5191 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005194#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005195 cur_arg += 2;
5196 continue;
5197 }
5198 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
5199 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005204 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5205 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5206 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005211 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005212 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005217
5218 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005219 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005220 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005221 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 }
5224 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005225 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005226 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005227 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 }
5231 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005232 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005233 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005234 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005235 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 }
5238 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005240 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005241 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 }
5245 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005247 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005248 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005251 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005252 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005254 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005255 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005257 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005258 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005259 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005260 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005261 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005262 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005264 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005265 }
5266 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005268 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005269 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005271 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5276 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005280
5281 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005282 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005283 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
5287 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005288 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005289 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005290 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 }
5294 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005295 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005296 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005297 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005298 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 }
5301 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005302 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005303 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005304 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005305 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307 }
5308 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005309 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005310 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005311 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005312 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005315 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005316 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005317 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005318 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005319 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005320 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005323 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005324
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325 if (curproxy == &defproxy) {
5326 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005327 err_code |= ERR_ALERT | ERR_FATAL;
5328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005330 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005331 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 if (*(args[1]) == 0) {
5334 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005338
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005339 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005340 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5341 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5342 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5347 }
5348 else if (*args[2]) {
5349 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5350 file, linenum, args[0], args[2]);
5351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
5353 }
5354
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005355 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005356 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005357 wl->s = strdup(args[1]);
5358 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005359 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 }
5361 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005362 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5364 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005367 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005368
Willy Tarreauade5ec42010-01-28 19:33:49 +01005369 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005370 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005371 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005372 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005374 }
5375 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005376 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005377 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005378 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005379 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 }
5382 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005383 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005384 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005385 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005386 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388 }
5389 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005390 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005395 }
5396
Willy Tarreauade5ec42010-01-28 19:33:49 +01005397 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005398 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005399 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005400 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402 }
5403 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005404 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005405 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005406 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005407 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005409 }
5410 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005411 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005412 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005413 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005414 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005416 }
5417 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005418 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005419
Willy Tarreaubaaee002006-06-26 02:48:02 +02005420 if (curproxy == &defproxy) {
5421 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005425 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005426 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427
Willy Tarreaubaaee002006-06-26 02:48:02 +02005428 if (*(args[1]) == 0) {
5429 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005432 }
5433
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005434 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005435 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5436 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5437 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005438 err_code |= ERR_ALERT | ERR_FATAL;
5439 goto out;
5440 }
5441 err_code |= warnif_cond_requires_req(cond, file, linenum);
5442 }
5443 else if (*args[2]) {
5444 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5445 file, linenum, args[0], args[2]);
5446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
5449
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005450 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005451 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005452 wl->s = strdup(args[1]);
5453 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 }
5455 else if (!strcmp(args[0], "errorloc") ||
5456 !strcmp(args[0], "errorloc302") ||
5457 !strcmp(args[0], "errorloc303")) { /* error location */
5458 int errnum, errlen;
5459 char *err;
5460
Willy Tarreau977b8e42006-12-29 14:19:17 +01005461 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005462 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005463
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005465 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 }
5469
5470 errnum = atol(args[1]);
5471 if (!strcmp(args[0], "errorloc303")) {
5472 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5473 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5474 } else {
5475 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5476 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5477 }
5478
Willy Tarreau0f772532006-12-23 20:51:41 +01005479 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5480 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005481 chunk_destroy(&curproxy->errmsg[rc]);
5482 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005483 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005486
5487 if (rc >= HTTP_ERR_SIZE) {
5488 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5489 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 free(err);
5491 }
5492 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005493 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5494 int errnum, errlen, fd;
5495 char *err;
5496 struct stat stat;
5497
5498 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005499 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005500
5501 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005502 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005505 }
5506
5507 fd = open(args[2], O_RDONLY);
5508 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5509 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5510 file, linenum, args[2], args[1]);
5511 if (fd >= 0)
5512 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005513 err_code |= ERR_ALERT | ERR_FATAL;
5514 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005515 }
5516
Willy Tarreau27a674e2009-08-17 07:23:33 +02005517 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005518 errlen = stat.st_size;
5519 } else {
5520 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005521 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005522 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005523 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005524 }
5525
5526 err = malloc(errlen); /* malloc() must succeed during parsing */
5527 errnum = read(fd, err, errlen);
5528 if (errnum != errlen) {
5529 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5530 file, linenum, args[2], args[1]);
5531 close(fd);
5532 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005533 err_code |= ERR_ALERT | ERR_FATAL;
5534 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005535 }
5536 close(fd);
5537
5538 errnum = atol(args[1]);
5539 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5540 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005541 chunk_destroy(&curproxy->errmsg[rc]);
5542 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005543 break;
5544 }
5545 }
5546
5547 if (rc >= HTTP_ERR_SIZE) {
5548 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5549 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005550 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005551 free(err);
5552 }
5553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005555 struct cfg_kw_list *kwl;
5556 int index;
5557
5558 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5559 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5560 if (kwl->kw[index].section != CFG_LISTEN)
5561 continue;
5562 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5563 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005564 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005565 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005566 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005567 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005568 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005569 err_code |= ERR_ALERT | ERR_FATAL;
5570 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005571 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005572 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005573 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005574 err_code |= ERR_WARN;
5575 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005576 }
Willy Tarreau93893792009-07-23 13:19:11 +02005577 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005578 }
5579 }
5580 }
5581
Willy Tarreau6daf3432008-01-22 16:44:08 +01005582 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585 }
Willy Tarreau93893792009-07-23 13:19:11 +02005586 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005587 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005588 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589}
5590
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005591int
5592cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5593{
5594
5595 int err_code = 0;
5596 const char *err;
5597
5598 if (!strcmp(args[0], "userlist")) { /* new userlist */
5599 struct userlist *newul;
5600
5601 if (!*args[1]) {
5602 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5603 file, linenum, args[0]);
5604 err_code |= ERR_ALERT | ERR_FATAL;
5605 goto out;
5606 }
5607
5608 err = invalid_char(args[1]);
5609 if (err) {
5610 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5611 file, linenum, *err, args[0], args[1]);
5612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614 }
5615
5616 for (newul = userlist; newul; newul = newul->next)
5617 if (!strcmp(newul->name, args[1])) {
5618 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5619 file, linenum, args[1]);
5620 err_code |= ERR_WARN;
5621 goto out;
5622 }
5623
5624 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5625 if (!newul) {
5626 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5627 err_code |= ERR_ALERT | ERR_ABORT;
5628 goto out;
5629 }
5630
5631 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5632 newul->name = strdup(args[1]);
5633
5634 if (!newul->groupusers | !newul->name) {
5635 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5636 err_code |= ERR_ALERT | ERR_ABORT;
5637 goto out;
5638 }
5639
5640 newul->next = userlist;
5641 userlist = newul;
5642
5643 } else if (!strcmp(args[0], "group")) { /* new group */
5644 int cur_arg, i;
5645 const char *err;
5646
5647 if (!*args[1]) {
5648 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5649 file, linenum, args[0]);
5650 err_code |= ERR_ALERT | ERR_FATAL;
5651 goto out;
5652 }
5653
5654 err = invalid_char(args[1]);
5655 if (err) {
5656 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5657 file, linenum, *err, args[0], args[1]);
5658 err_code |= ERR_ALERT | ERR_FATAL;
5659 goto out;
5660 }
5661
5662 for(i = 0; i < userlist->grpcnt; i++)
5663 if (!strcmp(userlist->groups[i], args[1])) {
5664 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5665 file, linenum, args[1], userlist->name);
5666 err_code |= ERR_ALERT;
5667 goto out;
5668 }
5669
5670 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5671 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5672 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5673 err_code |= ERR_ALERT | ERR_FATAL;
5674 goto out;
5675 }
5676
5677 cur_arg = 2;
5678
5679 while (*args[cur_arg]) {
5680 if (!strcmp(args[cur_arg], "users")) {
5681 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5682 cur_arg += 2;
5683 continue;
5684 } else {
5685 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5686 file, linenum, args[0]);
5687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
5689 }
5690 }
5691
5692 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5693 } else if (!strcmp(args[0], "user")) { /* new user */
5694 struct auth_users *newuser;
5695 int cur_arg;
5696
5697 if (!*args[1]) {
5698 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5699 file, linenum, args[0]);
5700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
5702 }
5703
5704 for (newuser = userlist->users; newuser; newuser = newuser->next)
5705 if (!strcmp(newuser->user, args[1])) {
5706 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5707 file, linenum, args[1], userlist->name);
5708 err_code |= ERR_ALERT;
5709 goto out;
5710 }
5711
5712 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5713 if (!newuser) {
5714 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5715 err_code |= ERR_ALERT | ERR_ABORT;
5716 goto out;
5717 }
5718
5719 newuser->user = strdup(args[1]);
5720
5721 newuser->next = userlist->users;
5722 userlist->users = newuser;
5723
5724 cur_arg = 2;
5725
5726 while (*args[cur_arg]) {
5727 if (!strcmp(args[cur_arg], "password")) {
5728#ifndef CONFIG_HAP_CRYPT
5729 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5730 file, linenum);
5731 err_code |= ERR_ALERT;
5732#endif
5733 newuser->pass = strdup(args[cur_arg + 1]);
5734 cur_arg += 2;
5735 continue;
5736 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5737 newuser->pass = strdup(args[cur_arg + 1]);
5738 newuser->flags |= AU_O_INSECURE;
5739 cur_arg += 2;
5740 continue;
5741 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005742 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005743 cur_arg += 2;
5744 continue;
5745 } else {
5746 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5747 file, linenum, args[0]);
5748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
5750 }
5751 }
5752 } else {
5753 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5754 err_code |= ERR_ALERT | ERR_FATAL;
5755 }
5756
5757out:
5758 return err_code;
5759}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760
5761/*
5762 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005763 * Returns the error code, 0 if OK, or any combination of :
5764 * - ERR_ABORT: must abort ASAP
5765 * - ERR_FATAL: we can continue parsing but not start the service
5766 * - ERR_WARN: a warning has been emitted
5767 * - ERR_ALERT: an alert has been emitted
5768 * Only the two first ones can stop processing, the two others are just
5769 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005771int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005773 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 FILE *f;
5775 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005776 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005777 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778
Willy Tarreaubaaee002006-06-26 02:48:02 +02005779 if ((f=fopen(file,"r")) == NULL)
5780 return -1;
5781
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005782 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005783 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005784 char *end;
5785 char *args[MAX_LINE_ARGS + 1];
5786 char *line = thisline;
5787
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 linenum++;
5789
5790 end = line + strlen(line);
5791
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005792 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5793 /* Check if we reached the limit and the last char is not \n.
5794 * Watch out for the last line without the terminating '\n'!
5795 */
5796 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005797 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005798 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005799 }
5800
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005802 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005803 line++;
5804
5805 arg = 0;
5806 args[arg] = line;
5807
5808 while (*line && arg < MAX_LINE_ARGS) {
5809 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5810 * C equivalent value. Other combinations left unchanged (eg: \1).
5811 */
5812 if (*line == '\\') {
5813 int skip = 0;
5814 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5815 *line = line[1];
5816 skip = 1;
5817 }
5818 else if (line[1] == 'r') {
5819 *line = '\r';
5820 skip = 1;
5821 }
5822 else if (line[1] == 'n') {
5823 *line = '\n';
5824 skip = 1;
5825 }
5826 else if (line[1] == 't') {
5827 *line = '\t';
5828 skip = 1;
5829 }
5830 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005831 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 unsigned char hex1, hex2;
5833 hex1 = toupper(line[2]) - '0';
5834 hex2 = toupper(line[3]) - '0';
5835 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5836 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5837 *line = (hex1<<4) + hex2;
5838 skip = 3;
5839 }
5840 else {
5841 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005842 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005843 }
5844 }
5845 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005846 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 end -= skip;
5848 }
5849 line++;
5850 }
5851 else if (*line == '#' || *line == '\n' || *line == '\r') {
5852 /* end of string, end of loop */
5853 *line = 0;
5854 break;
5855 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005856 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005857 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005858 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005859 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860 line++;
5861 args[++arg] = line;
5862 }
5863 else {
5864 line++;
5865 }
5866 }
5867
5868 /* empty line */
5869 if (!**args)
5870 continue;
5871
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005872 if (*line) {
5873 /* we had to stop due to too many args.
5874 * Let's terminate the string, print the offending part then cut the
5875 * last arg.
5876 */
5877 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5878 line++;
5879 *line = '\0';
5880
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005881 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005882 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005883 err_code |= ERR_ALERT | ERR_FATAL;
5884 args[arg] = line;
5885 }
5886
Willy Tarreau540abe42007-05-02 20:50:16 +02005887 /* zero out remaining args and ensure that at least one entry
5888 * is zeroed out.
5889 */
5890 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 args[arg] = line;
5892 }
5893
Willy Tarreau3842f002009-06-14 11:39:52 +02005894 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005895 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005896 char *tmp;
5897
Willy Tarreau3842f002009-06-14 11:39:52 +02005898 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005899 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005900 for (arg=0; *args[arg+1]; arg++)
5901 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005902 *tmp = '\0'; // fix the next arg to \0
5903 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005904 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005905 else if (!strcmp(args[0], "default")) {
5906 kwm = KWM_DEF;
5907 for (arg=0; *args[arg+1]; arg++)
5908 args[arg] = args[arg+1]; // shift args after inversion
5909 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005910
William Lallemand0f99e342011-10-12 17:50:54 +02005911 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5912 strcmp(args[0], "log") != 0) {
5913 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005914 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005915 }
5916
Willy Tarreau977b8e42006-12-29 14:19:17 +01005917 if (!strcmp(args[0], "listen") ||
5918 !strcmp(args[0], "frontend") ||
5919 !strcmp(args[0], "backend") ||
5920 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005921 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005923 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005924 cursection = strdup(args[0]);
5925 }
5926 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005927 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005928 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005929 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005930 }
5931 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005932 confsect = CFG_USERLIST;
5933 free(cursection);
5934 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005935 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005936 else if (!strcmp(args[0], "peers")) {
5937 confsect = CFG_PEERS;
5938 free(cursection);
5939 cursection = strdup(args[0]);
5940 }
5941
Willy Tarreaubaaee002006-06-26 02:48:02 +02005942 /* else it's a section keyword */
5943
5944 switch (confsect) {
5945 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005946 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 break;
5948 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005949 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005950 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005951 case CFG_USERLIST:
5952 err_code |= cfg_parse_users(file, linenum, args, kwm);
5953 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005954 case CFG_PEERS:
5955 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5956 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005958 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005959 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005960 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005961
5962 if (err_code & ERR_ABORT)
5963 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005964 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005965 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005966 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005967 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005968 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005969}
5970
Willy Tarreaubb925012009-07-23 13:36:36 +02005971/*
5972 * Returns the error code, 0 if OK, or any combination of :
5973 * - ERR_ABORT: must abort ASAP
5974 * - ERR_FATAL: we can continue parsing but not start the service
5975 * - ERR_WARN: a warning has been emitted
5976 * - ERR_ALERT: an alert has been emitted
5977 * Only the two first ones can stop processing, the two others are just
5978 * indicators.
5979 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005980int check_config_validity()
5981{
5982 int cfgerr = 0;
5983 struct proxy *curproxy = NULL;
5984 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005985 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005986 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005987 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988
5989 /*
5990 * Now, check for the integrity of all that we have collected.
5991 */
5992
5993 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005994 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005996 /* first, we will invert the proxy list order */
5997 curproxy = NULL;
5998 while (proxy) {
5999 struct proxy *next;
6000
6001 next = proxy->next;
6002 proxy->next = curproxy;
6003 curproxy = proxy;
6004 if (!next)
6005 break;
6006 proxy = next;
6007 }
6008
Willy Tarreaubaaee002006-06-26 02:48:02 +02006009 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006010 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006011 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006012 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006013 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006014 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006015 unsigned int next_id;
6016
6017 if (!curproxy->uuid) {
6018 /* proxy ID not set, use automatic numbering with first
6019 * spare entry starting with next_pxid.
6020 */
6021 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6022 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6023 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006024 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006025 next_pxid++;
6026
Willy Tarreau55ea7572007-06-17 19:56:27 +02006027
Willy Tarreaubaaee002006-06-26 02:48:02 +02006028 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006029 /* ensure we don't keep listeners uselessly bound */
6030 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006031 curproxy = curproxy->next;
6032 continue;
6033 }
6034
Willy Tarreauff01a212009-03-15 13:46:16 +01006035 switch (curproxy->mode) {
6036 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006037 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006038 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006039 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6040 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006041 cfgerr++;
6042 }
6043
6044 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006045 Warning("config : servers will be ignored for %s '%s'.\n",
6046 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006047 break;
6048
6049 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006050 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006051 break;
6052
6053 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006054 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006055 break;
6056 }
6057
6058 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006059 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
6060 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006061 cfgerr++;
6062 }
Willy Tarreauff01a212009-03-15 13:46:16 +01006063
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006064 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006065 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006066 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006067 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6068 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006069 cfgerr++;
6070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006071#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006072 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006073 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6074 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006075 cfgerr++;
6076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006077#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006078 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006079 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6080 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006081 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006082 }
6083 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006084 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006085 /* If no LB algo is set in a backend, and we're not in
6086 * transparent mode, dispatch mode nor proxy mode, we
6087 * want to use balance roundrobin by default.
6088 */
6089 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6090 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 }
6092 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006093
Willy Tarreau1620ec32011-08-06 17:05:02 +02006094 if (curproxy->options & PR_O_DISPATCH)
6095 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6096 else if (curproxy->options & PR_O_HTTP_PROXY)
6097 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6098 else if (curproxy->options & PR_O_TRANSP)
6099 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006100
Willy Tarreau1620ec32011-08-06 17:05:02 +02006101 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6102 if (curproxy->options & PR_O_DISABLE404) {
6103 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6104 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6105 err_code |= ERR_WARN;
6106 curproxy->options &= ~PR_O_DISABLE404;
6107 }
6108 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6109 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6110 "send-state", proxy_type_str(curproxy), curproxy->id);
6111 err_code |= ERR_WARN;
6112 curproxy->options &= ~PR_O2_CHK_SNDST;
6113 }
Willy Tarreauef781042010-01-27 11:53:01 +01006114 }
6115
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006116 /* if a default backend was specified, let's find it */
6117 if (curproxy->defbe.name) {
6118 struct proxy *target;
6119
Alex Williams96532db2009-11-01 21:27:13 -05006120 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006121 if (!target) {
6122 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6123 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006124 cfgerr++;
6125 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006126 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6127 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006128 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006129 } else {
6130 free(curproxy->defbe.name);
6131 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006132 /* we force the backend to be present on at least all of
6133 * the frontend's processes.
6134 */
6135 target->bind_proc = curproxy->bind_proc ?
6136 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006137
6138 /* Emit a warning if this proxy also has some servers */
6139 if (curproxy->srv) {
6140 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6141 curproxy->id);
6142 err_code |= ERR_WARN;
6143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006144 }
6145 }
6146
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006147 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006148 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6149 /* map jump target for ACT_SETBE in req_rep chain */
6150 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006151 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006152 struct proxy *target;
6153
Willy Tarreaua496b602006-12-17 23:15:24 +01006154 if (exp->action != ACT_SETBE)
6155 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006156
Alex Williams96532db2009-11-01 21:27:13 -05006157 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006158 if (!target) {
6159 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6160 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006161 cfgerr++;
6162 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006163 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6164 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006165 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006166 } else {
6167 free((void *)exp->replace);
6168 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006169 /* we force the backend to be present on at least all of
6170 * the frontend's processes.
6171 */
6172 target->bind_proc = curproxy->bind_proc ?
6173 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006174 }
6175 }
6176 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006177
6178 /* find the target proxy for 'use_backend' rules */
6179 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006180 struct proxy *target;
6181
Alex Williams96532db2009-11-01 21:27:13 -05006182 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006183
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006184 if (!target) {
6185 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6186 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006187 cfgerr++;
6188 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006189 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6190 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006191 cfgerr++;
6192 } else {
6193 free((void *)rule->be.name);
6194 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006195 /* we force the backend to be present on at least all of
6196 * the frontend's processes.
6197 */
6198 target->bind_proc = curproxy->bind_proc ?
6199 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006200 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006201 }
6202
6203 /* find the target proxy for 'use_backend' rules */
6204 list_for_each_entry(srule, &curproxy->server_rules, list) {
6205 struct server *target = findserver(curproxy, srule->srv.name);
6206
6207 if (!target) {
6208 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6209 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6210 cfgerr++;
6211 continue;
6212 }
6213 free((void *)srule->srv.name);
6214 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006215 }
6216
Emeric Brunb982a3d2010-01-04 15:45:53 +01006217 /* find the target table for 'stick' rules */
6218 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6219 struct proxy *target;
6220
Emeric Brun1d33b292010-01-04 15:47:17 +01006221 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6222 if (mrule->flags & STK_IS_STORE)
6223 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6224
Emeric Brunb982a3d2010-01-04 15:45:53 +01006225 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006226 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006227 else
6228 target = curproxy;
6229
6230 if (!target) {
6231 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6232 curproxy->id, mrule->table.name);
6233 cfgerr++;
6234 }
6235 else if (target->table.size == 0) {
6236 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6237 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6238 cfgerr++;
6239 }
Willy Tarreau12785782012-04-27 21:37:17 +02006240 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6241 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006242 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6243 cfgerr++;
6244 }
6245 else {
6246 free((void *)mrule->table.name);
6247 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006248 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006249 }
6250 }
6251
6252 /* find the target table for 'store response' rules */
6253 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6254 struct proxy *target;
6255
Emeric Brun1d33b292010-01-04 15:47:17 +01006256 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6257
Emeric Brunb982a3d2010-01-04 15:45:53 +01006258 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006259 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006260 else
6261 target = curproxy;
6262
6263 if (!target) {
6264 Alert("Proxy '%s': unable to find store table '%s'.\n",
6265 curproxy->id, mrule->table.name);
6266 cfgerr++;
6267 }
6268 else if (target->table.size == 0) {
6269 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6270 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6271 cfgerr++;
6272 }
Willy Tarreau12785782012-04-27 21:37:17 +02006273 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6274 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006275 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6276 cfgerr++;
6277 }
6278 else {
6279 free((void *)mrule->table.name);
6280 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006281 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006282 }
6283 }
6284
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006285 /* find the target table for 'tcp-request' layer 4 rules */
6286 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6287 struct proxy *target;
6288
Willy Tarreau56123282010-08-06 19:06:56 +02006289 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006290 continue;
6291
6292 if (trule->act_prm.trk_ctr.table.n)
6293 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6294 else
6295 target = curproxy;
6296
6297 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006298 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6299 curproxy->id, trule->act_prm.trk_ctr.table.n,
6300 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006301 cfgerr++;
6302 }
6303 else if (target->table.size == 0) {
6304 Alert("Proxy '%s': table '%s' used but not configured.\n",
6305 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6306 cfgerr++;
6307 }
6308 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006309 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 +02006310 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6311 cfgerr++;
6312 }
6313 else {
6314 free(trule->act_prm.trk_ctr.table.n);
6315 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006316 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006317 * to pass a list of counters to track and allocate them right here using
6318 * stktable_alloc_data_type().
6319 */
6320 }
6321 }
6322
Willy Tarreaud1f96522010-08-03 19:34:32 +02006323 /* find the target table for 'tcp-request' layer 6 rules */
6324 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6325 struct proxy *target;
6326
Willy Tarreau56123282010-08-06 19:06:56 +02006327 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006328 continue;
6329
6330 if (trule->act_prm.trk_ctr.table.n)
6331 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6332 else
6333 target = curproxy;
6334
6335 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006336 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6337 curproxy->id, trule->act_prm.trk_ctr.table.n,
6338 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006339 cfgerr++;
6340 }
6341 else if (target->table.size == 0) {
6342 Alert("Proxy '%s': table '%s' used but not configured.\n",
6343 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6344 cfgerr++;
6345 }
6346 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006347 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 +02006348 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6349 cfgerr++;
6350 }
6351 else {
6352 free(trule->act_prm.trk_ctr.table.n);
6353 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006354 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006355 * to pass a list of counters to track and allocate them right here using
6356 * stktable_alloc_data_type().
6357 */
6358 }
6359 }
6360
Emeric Brun32da3c42010-09-23 18:39:19 +02006361 if (curproxy->table.peers.name) {
6362 struct peers *curpeers = peers;
6363
6364 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6365 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6366 free((void *)curproxy->table.peers.name);
6367 curproxy->table.peers.p = peers;
6368 break;
6369 }
6370 }
6371
6372 if (!curpeers) {
6373 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6374 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006375 free((void *)curproxy->table.peers.name);
6376 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006377 cfgerr++;
6378 }
6379 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006380 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6381 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006382 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006383 cfgerr++;
6384 }
6385 }
6386
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006387 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006388 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006389 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6390 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6391 "proxy", curproxy->id);
6392 cfgerr++;
6393 goto out_uri_auth_compat;
6394 }
6395
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006396 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006397 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006398 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006399 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006400
Willy Tarreau95fa4692010-02-01 13:05:50 +01006401 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6402 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006403
6404 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006405 uri_auth_compat_req[i++] = "realm";
6406 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6407 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006408
Willy Tarreau95fa4692010-02-01 13:05:50 +01006409 uri_auth_compat_req[i++] = "unless";
6410 uri_auth_compat_req[i++] = "{";
6411 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6412 uri_auth_compat_req[i++] = "}";
6413 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006414
Willy Tarreauff011f22011-01-06 17:51:27 +01006415 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6416 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006417 cfgerr++;
6418 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006419 }
6420
Willy Tarreauff011f22011-01-06 17:51:27 +01006421 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006422
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006423 if (curproxy->uri_auth->auth_realm) {
6424 free(curproxy->uri_auth->auth_realm);
6425 curproxy->uri_auth->auth_realm = NULL;
6426 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006427
6428 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006429 }
6430out_uri_auth_compat:
6431
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006432 cfgerr += acl_find_targets(curproxy);
6433
Willy Tarreau2738a142006-07-08 17:28:09 +02006434 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006435 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006436 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006437 (!curproxy->timeout.connect ||
6438 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006439 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006440 " | While not properly invalid, you will certainly encounter various problems\n"
6441 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006442 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006443 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006444 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006445 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006446
Willy Tarreau1fa31262007-12-03 00:36:16 +01006447 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6448 * We must still support older configurations, so let's find out whether those
6449 * parameters have been set or must be copied from contimeouts.
6450 */
6451 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006452 if (!curproxy->timeout.tarpit ||
6453 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006454 /* tarpit timeout not set. We search in the following order:
6455 * default.tarpit, curr.connect, default.connect.
6456 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006457 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006458 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006459 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006460 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006461 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006462 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006463 }
6464 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006465 (!curproxy->timeout.queue ||
6466 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006467 /* queue timeout not set. We search in the following order:
6468 * default.queue, curr.connect, default.connect.
6469 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006470 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006471 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006472 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006473 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006474 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006475 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006476 }
6477 }
6478
Willy Tarreau1620ec32011-08-06 17:05:02 +02006479 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006480 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6481 curproxy->check_req = (char *)malloc(curproxy->check_len);
6482 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006483 }
6484
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006485 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006486 if (curproxy->nb_req_cap) {
6487 if (curproxy->mode == PR_MODE_HTTP) {
6488 curproxy->req_cap_pool = create_pool("ptrcap",
6489 curproxy->nb_req_cap * sizeof(char *),
6490 MEM_F_SHARED);
6491 } else {
6492 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6493 proxy_type_str(curproxy), curproxy->id);
6494 err_code |= ERR_WARN;
6495 curproxy->to_log &= ~LW_REQHDR;
6496 curproxy->nb_req_cap = 0;
6497 }
6498 }
6499
6500 if (curproxy->nb_rsp_cap) {
6501 if (curproxy->mode == PR_MODE_HTTP) {
6502 curproxy->rsp_cap_pool = create_pool("ptrcap",
6503 curproxy->nb_rsp_cap * sizeof(char *),
6504 MEM_F_SHARED);
6505 } else {
6506 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6507 proxy_type_str(curproxy), curproxy->id);
6508 err_code |= ERR_WARN;
6509 curproxy->to_log &= ~LW_REQHDR;
6510 curproxy->nb_rsp_cap = 0;
6511 }
6512 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006513
Willy Tarreau196729e2012-05-31 19:30:26 +02006514 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006515 if (!(curproxy->cap & PR_CAP_FE)) {
6516 if (curproxy->logformat_string != default_http_log_format &&
6517 curproxy->logformat_string != default_tcp_log_format &&
6518 curproxy->logformat_string != clf_http_log_format)
6519 free(curproxy->logformat_string);
6520 curproxy->logformat_string = NULL;
6521 }
6522
Willy Tarreau196729e2012-05-31 19:30:26 +02006523 if (curproxy->logformat_string)
6524 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6525
6526 if (curproxy->uniqueid_format_string)
6527 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6528
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529 /* first, we will invert the servers list order */
6530 newsrv = NULL;
6531 while (curproxy->srv) {
6532 struct server *next;
6533
6534 next = curproxy->srv->next;
6535 curproxy->srv->next = newsrv;
6536 newsrv = curproxy->srv;
6537 if (!next)
6538 break;
6539 curproxy->srv = next;
6540 }
6541
Willy Tarreaudd701652010-05-25 23:03:02 +02006542 /* assign automatic UIDs to servers which don't have one yet */
6543 next_id = 1;
6544 newsrv = curproxy->srv;
6545 while (newsrv != NULL) {
6546 if (!newsrv->puid) {
6547 /* server ID not set, use automatic numbering with first
6548 * spare entry starting with next_svid.
6549 */
6550 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6551 newsrv->conf.id.key = newsrv->puid = next_id;
6552 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6553 }
6554 next_id++;
6555 newsrv = newsrv->next;
6556 }
6557
Willy Tarreau20697042007-11-15 23:26:18 +01006558 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006559 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006560
Willy Tarreau62c3be22012-01-20 13:12:32 +01006561 /*
6562 * If this server supports a maxconn parameter, it needs a dedicated
6563 * tasks to fill the emptied slots when a connection leaves.
6564 * Also, resolve deferred tracking dependency if needed.
6565 */
6566 newsrv = curproxy->srv;
6567 while (newsrv != NULL) {
6568 if (newsrv->minconn > newsrv->maxconn) {
6569 /* Only 'minconn' was specified, or it was higher than or equal
6570 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6571 * this will avoid further useless expensive computations.
6572 */
6573 newsrv->maxconn = newsrv->minconn;
6574 } else if (newsrv->maxconn && !newsrv->minconn) {
6575 /* minconn was not specified, so we set it to maxconn */
6576 newsrv->minconn = newsrv->maxconn;
6577 }
6578
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006579#ifdef USE_OPENSSL
6580#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6581#define SSL_OP_NO_COMPRESSION 0
6582#endif
6583#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6584#define SSL_MODE_RELEASE_BUFFERS 0
6585#endif
6586#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6587#define SSL_OP_NO_COMPRESSION 0
6588#endif
6589 if (newsrv->use_ssl) {
6590 int ssloptions =
6591 SSL_OP_ALL | /* all known workarounds for bugs */
6592 SSL_OP_NO_SSLv2 |
6593 SSL_OP_NO_COMPRESSION;
6594 int sslmode =
6595 SSL_MODE_ENABLE_PARTIAL_WRITE |
6596 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6597 SSL_MODE_RELEASE_BUFFERS;
6598
6599 /* Initiate SSL context for current server */
6600 newsrv->ssl_ctx.reused_sess = NULL;
6601 newsrv->data = &ssl_sock;
6602 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6603 if(!newsrv->ssl_ctx.ctx) {
6604
6605 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6606 proxy_type_str(curproxy), curproxy->id,
6607 newsrv->id);
6608 cfgerr++;
6609 goto next_srv;
6610 }
6611
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006612 if (newsrv->ssl_ctx.nosslv3)
6613 ssloptions |= SSL_OP_NO_SSLv3;
6614 if (newsrv->ssl_ctx.notlsv1)
6615 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006616 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6617 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6618 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6619 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006620 if (newsrv->ssl_ctx.ciphers &&
6621 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6622 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6623 curproxy->id, newsrv->id,
6624 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6625 cfgerr++;
6626 goto next_srv;
6627 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006628 }
6629#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006630 if (newsrv->trackit) {
6631 struct proxy *px;
6632 struct server *srv;
6633 char *pname, *sname;
6634
6635 pname = newsrv->trackit;
6636 sname = strrchr(pname, '/');
6637
6638 if (sname)
6639 *sname++ = '\0';
6640 else {
6641 sname = pname;
6642 pname = NULL;
6643 }
6644
6645 if (pname) {
6646 px = findproxy(pname, PR_CAP_BE);
6647 if (!px) {
6648 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6649 proxy_type_str(curproxy), curproxy->id,
6650 newsrv->id, pname);
6651 cfgerr++;
6652 goto next_srv;
6653 }
6654 } else
6655 px = curproxy;
6656
6657 srv = findserver(px, sname);
6658 if (!srv) {
6659 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6660 proxy_type_str(curproxy), curproxy->id,
6661 newsrv->id, sname);
6662 cfgerr++;
6663 goto next_srv;
6664 }
6665
6666 if (!(srv->state & SRV_CHECKED)) {
6667 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6668 "tracking as it does not have checks enabled.\n",
6669 proxy_type_str(curproxy), curproxy->id,
6670 newsrv->id, px->id, srv->id);
6671 cfgerr++;
6672 goto next_srv;
6673 }
6674
6675 if (curproxy != px &&
6676 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6677 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6678 "tracking: disable-on-404 option inconsistency.\n",
6679 proxy_type_str(curproxy), curproxy->id,
6680 newsrv->id, px->id, srv->id);
6681 cfgerr++;
6682 goto next_srv;
6683 }
6684
6685 /* if the other server is forced disabled, we have to do the same here */
6686 if (srv->state & SRV_MAINTAIN) {
6687 newsrv->state |= SRV_MAINTAIN;
6688 newsrv->state &= ~SRV_RUNNING;
6689 newsrv->health = 0;
6690 }
6691
6692 newsrv->track = srv;
6693 newsrv->tracknext = srv->tracknext;
6694 srv->tracknext = newsrv;
6695
6696 free(newsrv->trackit);
6697 newsrv->trackit = NULL;
6698 }
6699 next_srv:
6700 newsrv = newsrv->next;
6701 }
6702
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006703 /* We have to initialize the server lookup mechanism depending
6704 * on what LB algorithm was choosen.
6705 */
6706
6707 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6708 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6709 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006710 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6711 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6712 init_server_map(curproxy);
6713 } else {
6714 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6715 fwrr_init_server_groups(curproxy);
6716 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006717 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006718
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006719 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006720 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6721 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6722 fwlc_init_server_tree(curproxy);
6723 } else {
6724 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6725 fas_init_server_tree(curproxy);
6726 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006727 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006728
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006729 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006730 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6731 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6732 chash_init_server_tree(curproxy);
6733 } else {
6734 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6735 init_server_map(curproxy);
6736 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006737 break;
6738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006739
6740 if (curproxy->options & PR_O_LOGASAP)
6741 curproxy->to_log &= ~LW_BYTES;
6742
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006743 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006744 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006745 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6746 proxy_type_str(curproxy), curproxy->id);
6747 err_code |= ERR_WARN;
6748 }
6749
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006750 if (curproxy->mode != PR_MODE_HTTP) {
6751 int optnum;
6752
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006753 if (curproxy->uri_auth) {
6754 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6755 proxy_type_str(curproxy), curproxy->id);
6756 err_code |= ERR_WARN;
6757 curproxy->uri_auth = NULL;
6758 }
6759
Willy Tarreau87cf5142011-08-19 22:57:24 +02006760 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006761 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6762 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6763 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006764 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006765 }
6766
6767 if (curproxy->options & PR_O_ORGTO) {
6768 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6769 "originalto", proxy_type_str(curproxy), curproxy->id);
6770 err_code |= ERR_WARN;
6771 curproxy->options &= ~PR_O_ORGTO;
6772 }
6773
6774 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6775 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6776 (curproxy->cap & cfg_opts[optnum].cap) &&
6777 (curproxy->options & cfg_opts[optnum].val)) {
6778 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6779 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6780 err_code |= ERR_WARN;
6781 curproxy->options &= ~cfg_opts[optnum].val;
6782 }
6783 }
6784
6785 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6786 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6787 (curproxy->cap & cfg_opts2[optnum].cap) &&
6788 (curproxy->options2 & cfg_opts2[optnum].val)) {
6789 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6790 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6791 err_code |= ERR_WARN;
6792 curproxy->options2 &= ~cfg_opts2[optnum].val;
6793 }
6794 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006795
Willy Tarreauefa5f512010-03-30 20:13:29 +02006796#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006797 if (curproxy->bind_hdr_occ) {
6798 curproxy->bind_hdr_occ = 0;
6799 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6800 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6801 err_code |= ERR_WARN;
6802 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006803#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006804 }
6805
Willy Tarreaubaaee002006-06-26 02:48:02 +02006806 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006807 * ensure that we're not cross-dressing a TCP server into HTTP.
6808 */
6809 newsrv = curproxy->srv;
6810 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006811 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006812 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6813 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006814 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006815 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006816
Willy Tarreau0cec3312011-10-31 13:49:26 +01006817 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6818 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6819 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6820 err_code |= ERR_WARN;
6821 }
6822
Willy Tarreauefa5f512010-03-30 20:13:29 +02006823#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006824 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6825 newsrv->bind_hdr_occ = 0;
6826 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6827 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6828 err_code |= ERR_WARN;
6829 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006830#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006831 newsrv = newsrv->next;
6832 }
6833
Willy Tarreauc1a21672009-08-16 22:37:44 +02006834 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006835 curproxy->accept = frontend_accept;
6836
Willy Tarreauc1a21672009-08-16 22:37:44 +02006837 if (curproxy->tcp_req.inspect_delay ||
6838 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006839 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006840
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006841 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006842 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006843 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006844 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006845
6846 /* both TCP and HTTP must check switching rules */
6847 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6848 }
6849
6850 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006851 if (curproxy->tcp_req.inspect_delay ||
6852 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6853 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6854
Emeric Brun97679e72010-09-23 17:56:44 +02006855 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6856 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6857
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006858 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006859 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006860 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006861 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006862
6863 /* If the backend does requires RDP cookie persistence, we have to
6864 * enable the corresponding analyser.
6865 */
6866 if (curproxy->options2 & PR_O2_RDPC_PRST)
6867 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6868 }
6869
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006870 listener = NULL;
6871 while (curproxy->listen) {
6872 struct listener *next;
6873
6874 next = curproxy->listen->next;
6875 curproxy->listen->next = listener;
6876 listener = curproxy->listen;
6877
6878 if (!next)
6879 break;
6880
6881 curproxy->listen = next;
6882 }
6883
Willy Tarreaue6b98942007-10-29 01:09:36 +01006884 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006885 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006886 listener = curproxy->listen;
6887 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006888 if (!listener->luid) {
6889 /* listener ID not set, use automatic numbering with first
6890 * spare entry starting with next_luid.
6891 */
6892 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6893 listener->conf.id.key = listener->luid = next_id;
6894 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006895 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006896 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006897
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006898 /* enable separate counters */
6899 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6900 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6901 if (!listener->name) {
6902 sprintf(trash, "sock-%d", listener->luid);
6903 listener->name = strdup(trash);
6904 }
6905 }
6906
Emeric Brun6e159292012-05-18 16:32:13 +02006907#ifdef USE_OPENSSL
David BERARDe566ecb2012-09-04 15:15:13 +02006908#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
6909#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
6910#endif
6911
Emeric Brun6e159292012-05-18 16:32:13 +02006912#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
6913#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
6914#endif
6915#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6916#define SSL_OP_NO_COMPRESSION 0
6917#endif
6918#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6919#define SSL_MODE_RELEASE_BUFFERS 0
6920#endif
6921 /* Initialize SSL */
6922 if (listener->ssl_cert) {
6923 int ssloptions =
6924 SSL_OP_ALL | /* all known workarounds for bugs */
6925 SSL_OP_NO_SSLv2 |
6926 SSL_OP_NO_COMPRESSION |
6927 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
6928 int sslmode =
6929 SSL_MODE_ENABLE_PARTIAL_WRITE |
6930 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6931 SSL_MODE_RELEASE_BUFFERS;
6932
6933 listener->data = &ssl_sock; /* data layer */
6934 listener->ssl_ctx.ctx = SSL_CTX_new(SSLv23_server_method());
6935 if (!listener->ssl_ctx.ctx) {
6936 Alert("Proxy '%s': unable to allocate SSL context to bind listener %d (%s:%d) using cert '%s'.\n",
6937 curproxy->id, listener->luid, listener->conf.file, listener->conf.line, listener->ssl_cert);
6938 cfgerr++;
6939 goto skip_ssl;
6940 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006941 if (listener->ssl_ctx.nosslv3)
6942 ssloptions |= SSL_OP_NO_SSLv3;
6943 if (listener->ssl_ctx.notlsv1)
6944 ssloptions |= SSL_OP_NO_TLSv1;
David BERARDe566ecb2012-09-04 15:15:13 +02006945 if (listener->ssl_ctx.prefer_server_ciphers)
6946 ssloptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brun6e159292012-05-18 16:32:13 +02006947 SSL_CTX_set_options(listener->ssl_ctx.ctx, ssloptions);
6948 SSL_CTX_set_mode(listener->ssl_ctx.ctx, sslmode);
6949 SSL_CTX_set_verify(listener->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
Emeric Brunfc32aca2012-09-03 12:10:29 +02006950 if (shared_context_init(global.tune.sslcachesize) < 0) {
Emeric Brunaa35f1f2012-09-03 11:53:36 +02006951 Alert("Unable to allocate SSL session cache.\n");
6952 cfgerr++;
6953 goto skip_ssl;
6954 }
6955 shared_context_set_cache(listener->ssl_ctx.ctx);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006956 if (listener->ssl_ctx.ciphers &&
6957 !SSL_CTX_set_cipher_list(listener->ssl_ctx.ctx, listener->ssl_ctx.ciphers)) {
6958 Alert("Proxy '%s': unable to set SSL cipher list to '%s' for listener %d (%s:%d) using cert '%s'.\n",
6959 curproxy->id, listener->ssl_ctx.ciphers, listener->luid,
6960 listener->conf.file, listener->conf.line, listener->ssl_cert);
6961 cfgerr++;
6962 goto skip_ssl;
6963 }
Emeric Brunaa35f1f2012-09-03 11:53:36 +02006964
Emeric Brune1f38db2012-09-03 20:36:47 +02006965 SSL_CTX_set_info_callback(listener->ssl_ctx.ctx, ssl_sock_infocbk);
Emeric Brun6e159292012-05-18 16:32:13 +02006966
6967 if (SSL_CTX_use_PrivateKey_file(listener->ssl_ctx.ctx, listener->ssl_cert, SSL_FILETYPE_PEM) <= 0) {
6968 Alert("Proxy '%s': unable to load SSL private key from file '%s' in listener %d (%s:%d).\n",
6969 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6970 cfgerr++;
6971 goto skip_ssl;
6972 }
6973
6974 if (SSL_CTX_use_certificate_chain_file(listener->ssl_ctx.ctx, listener->ssl_cert) <= 0) {
6975 Alert("Proxy '%s': unable to load SSL certificate from file '%s' in listener %d (%s:%d).\n",
6976 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6977 cfgerr++;
6978 goto skip_ssl;
6979 }
6980 }
6981 skip_ssl:
6982#endif /* USE_OPENSSL */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006983 if (curproxy->options & PR_O_TCP_NOLING)
6984 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006985 if (!listener->maxconn)
6986 listener->maxconn = curproxy->maxconn;
6987 if (!listener->backlog)
6988 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006989 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006990 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006991 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006992 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006993 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006994
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006995 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6996 listener->options |= LI_O_TCP_RULES;
6997
Willy Tarreaude3041d2010-05-31 10:56:17 +02006998 if (curproxy->mon_mask.s_addr)
6999 listener->options |= LI_O_CHK_MONNET;
7000
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007001 /* smart accept mode is automatic in HTTP mode */
7002 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreaufbac6632012-09-03 22:33:40 +02007003 ((curproxy->mode == PR_MODE_HTTP || listener->ssl_cert) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007004 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7005 listener->options |= LI_O_NOQUICKACK;
7006
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02007007 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01007008 listener = listener->next;
7009 }
7010
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007011 /* Check multi-process mode compatibility for the current proxy */
7012 if (global.nbproc > 1) {
7013 int nbproc = 0;
7014 if (curproxy->bind_proc) {
7015 int proc;
7016 for (proc = 0; proc < global.nbproc; proc++) {
7017 if (curproxy->bind_proc & (1 << proc)) {
7018 nbproc++;
7019 }
7020 }
7021 } else {
7022 nbproc = global.nbproc;
7023 }
7024 if (curproxy->table.peers.name) {
7025 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7026 curproxy->id);
7027 cfgerr++;
7028 }
7029 if (nbproc > 1) {
7030 if (curproxy->uri_auth) {
7031 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7032 curproxy->id);
7033 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7034 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7035 curproxy->id);
7036 }
7037 }
7038 if (curproxy->appsession_name) {
7039 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7040 curproxy->id);
7041 }
7042 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7043 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7044 curproxy->id);
7045 }
7046 }
7047 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007048
7049 /* create the task associated with the proxy */
7050 curproxy->task = task_new();
7051 if (curproxy->task) {
7052 curproxy->task->context = curproxy;
7053 curproxy->task->process = manage_proxy;
7054 /* no need to queue, it will be done automatically if some
7055 * listener gets limited.
7056 */
7057 curproxy->task->expire = TICK_ETERNITY;
7058 } else {
7059 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7060 curproxy->id);
7061 cfgerr++;
7062 }
7063
Willy Tarreaubaaee002006-06-26 02:48:02 +02007064 curproxy = curproxy->next;
7065 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007066
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007067 /* Check multi-process mode compatibility */
7068 if (global.nbproc > 1) {
7069 if (global.stats_fe) {
7070 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
7071 }
7072 }
7073
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007074 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7075 struct auth_users *curuser;
7076 int g;
7077
7078 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7079 unsigned int group_mask = 0;
7080 char *group = NULL;
7081
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007082 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007083 continue;
7084
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007085 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007086
7087 for (g = 0; g < curuserlist->grpcnt; g++)
7088 if (!strcmp(curuserlist->groups[g], group))
7089 break;
7090
7091 if (g == curuserlist->grpcnt) {
7092 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7093 curuserlist->name, group, curuser->user);
7094 err_code |= ERR_ALERT | ERR_FATAL;
7095 goto out;
7096 }
7097
7098 group_mask |= (1 << g);
7099 }
7100
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007101 free(curuser->u.groups);
7102 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007103 }
7104
7105 for (g = 0; g < curuserlist->grpcnt; g++) {
7106 char *user = NULL;
7107
7108 if (!curuserlist->groupusers[g])
7109 continue;
7110
7111 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7112 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7113 if (!strcmp(curuser->user, user))
7114 break;
7115
7116 if (!curuser) {
7117 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7118 curuserlist->name, user, curuserlist->groups[g]);
7119 err_code |= ERR_ALERT | ERR_FATAL;
7120 goto out;
7121 }
7122
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007123 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007124 }
7125
7126 free(curuserlist->groupusers[g]);
7127 }
7128
7129 free(curuserlist->groupusers);
7130
7131#ifdef DEBUG_AUTH
7132 for (g = 0; g < curuserlist->grpcnt; g++) {
7133 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7134
7135 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007136 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007137 fprintf(stderr, " %s", curuser->user);
7138 }
7139
7140 fprintf(stderr, "\n");
7141 }
7142#endif
7143
Willy Tarreaufbb78422011-06-05 15:38:35 +02007144 }
7145
7146 /* automatically compute fullconn if not set. We must not do it in the
7147 * loop above because cross-references are not yet fully resolved.
7148 */
7149 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7150 /* If <fullconn> is not set, let's set it to 10% of the sum of
7151 * the possible incoming frontend's maxconns.
7152 */
7153 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7154 struct proxy *fe;
7155 int total = 0;
7156
7157 /* sum up the number of maxconns of frontends which
7158 * reference this backend at least once or which are
7159 * the same one ('listen').
7160 */
7161 for (fe = proxy; fe; fe = fe->next) {
7162 struct switching_rule *rule;
7163 struct hdr_exp *exp;
7164 int found = 0;
7165
7166 if (!(fe->cap & PR_CAP_FE))
7167 continue;
7168
7169 if (fe == curproxy) /* we're on a "listen" instance */
7170 found = 1;
7171
7172 if (fe->defbe.be == curproxy) /* "default_backend" */
7173 found = 1;
7174
7175 /* check if a "use_backend" rule matches */
7176 if (!found) {
7177 list_for_each_entry(rule, &fe->switching_rules, list) {
7178 if (rule->be.backend == curproxy) {
7179 found = 1;
7180 break;
7181 }
7182 }
7183 }
7184
7185 /* check if a "reqsetbe" rule matches */
7186 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7187 if (exp->action == ACT_SETBE &&
7188 (struct proxy *)exp->replace == curproxy) {
7189 found = 1;
7190 break;
7191 }
7192 }
7193
7194 /* now we've checked all possible ways to reference a backend
7195 * from a frontend.
7196 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007197 if (!found)
7198 continue;
7199 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007200 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007201 /* we have the sum of the maxconns in <total>. We only
7202 * keep 10% of that sum to set the default fullconn, with
7203 * a hard minimum of 1 (to avoid a divide by zero).
7204 */
7205 curproxy->fullconn = (total + 9) / 10;
7206 if (!curproxy->fullconn)
7207 curproxy->fullconn = 1;
7208 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007209 }
7210
Willy Tarreau056f5682010-06-06 15:51:11 +02007211 /* initialize stick-tables on backend capable proxies. This must not
7212 * be done earlier because the data size may be discovered while parsing
7213 * other proxies.
7214 */
7215 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007216 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007217
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007218 /*
7219 * Recount currently required checks.
7220 */
7221
7222 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7223 int optnum;
7224
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007225 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7226 if (curproxy->options & cfg_opts[optnum].val)
7227 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007228
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007229 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7230 if (curproxy->options2 & cfg_opts2[optnum].val)
7231 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007232 }
7233
Willy Tarreau122541c2011-09-07 21:24:49 +02007234 if (peers) {
7235 struct peers *curpeers = peers, **last;
7236 struct peer *p, *pb;
7237
7238 /* Remove all peers sections which don't have a valid listener.
7239 * This can happen when a peers section is never referenced and
7240 * does not contain a local peer.
7241 */
7242 last = &peers;
7243 while (*last) {
7244 curpeers = *last;
7245 if (curpeers->peers_fe) {
7246 last = &curpeers->next;
7247 continue;
7248 }
7249
7250 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7251 curpeers->id, localpeer);
7252
7253 p = curpeers->remote;
7254 while (p) {
7255 pb = p->next;
7256 free(p->id);
7257 free(p);
7258 p = pb;
7259 }
7260
7261 /* Destroy and unlink this curpeers section.
7262 * Note: curpeers is backed up into *last.
7263 */
7264 free(curpeers->id);
7265 curpeers = curpeers->next;
7266 free(*last);
7267 *last = curpeers;
7268 }
7269 }
7270
Willy Tarreauac1932d2011-10-24 19:14:41 +02007271 if (!global.tune.max_http_hdr)
7272 global.tune.max_http_hdr = MAX_HTTP_HDR;
7273
Willy Tarreau34eb6712011-10-24 18:15:04 +02007274 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007275 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007276 MEM_F_SHARED);
7277
Willy Tarreaubb925012009-07-23 13:36:36 +02007278 if (cfgerr > 0)
7279 err_code |= ERR_ALERT | ERR_FATAL;
7280 out:
7281 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007282}
7283
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007284/*
7285 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7286 * parsing sessions.
7287 */
7288void cfg_register_keywords(struct cfg_kw_list *kwl)
7289{
7290 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7291}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007292
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007293/*
7294 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7295 */
7296void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7297{
7298 LIST_DEL(&kwl->list);
7299 LIST_INIT(&kwl->list);
7300}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007301
7302/*
7303 * Local variables:
7304 * c-indent-level: 8
7305 * c-basic-offset: 8
7306 * End:
7307 */