blob: c316bed8e27e90bc2b8ec510f1ca9db3ec6e3aef [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 Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
36#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020037#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020042#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020045#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020046#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010048#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020052#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020061#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010063#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020064#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010066#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
Emeric Brunfc0421f2012-09-07 17:30:07 +020068#ifdef USE_OPENSSL
69#include <types/ssl_sock.h>
70#include <proto/ssl_sock.h>
71#include <proto/shctx.h>
72#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020073
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 Tarreau2a65ff02012-09-13 17:54:29 +02001381 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382
Willy Tarreau977b8e42006-12-29 14:19:17 +01001383 if (!strcmp(args[0], "listen"))
1384 rc = PR_CAP_LISTEN;
1385 else if (!strcmp(args[0], "frontend"))
1386 rc = PR_CAP_FE | PR_CAP_RS;
1387 else if (!strcmp(args[0], "backend"))
1388 rc = PR_CAP_BE | PR_CAP_RS;
1389 else if (!strcmp(args[0], "ruleset"))
1390 rc = PR_CAP_RS;
1391 else
1392 rc = PR_CAP_NONE;
1393
1394 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395 if (!*args[1]) {
1396 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1397 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1398 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001399 err_code |= ERR_ALERT | ERR_ABORT;
1400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001402
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001403 err = invalid_char(args[1]);
1404 if (err) {
1405 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1406 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001407 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001408 }
1409
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001410 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1411 /*
1412 * If there are two proxies with the same name only following
1413 * combinations are allowed:
1414 *
1415 * listen backend frontend ruleset
1416 * listen - - - -
1417 * backend - - OK -
1418 * frontend - OK - -
1419 * ruleset - - - -
1420 */
1421
1422 if (!strcmp(curproxy->id, args[1]) &&
1423 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1424 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001425 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1426 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1427 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001428 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001429 }
1430 }
1431
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1433 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001434 err_code |= ERR_ALERT | ERR_ABORT;
1435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001437
Willy Tarreau97cb7802010-01-03 20:23:58 +01001438 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 curproxy->next = proxy;
1440 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001441 curproxy->conf.file = file;
1442 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001443 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001445 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446
1447 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001448 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001449 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001450 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001451 err_code |= ERR_FATAL;
1452 goto out;
1453 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001454 new = curproxy->listen;
1455 while (new != last) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001456 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001457 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001458 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 }
1460
1461 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001462 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001463 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001464
Willy Tarreaubaaee002006-06-26 02:48:02 +02001465 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001467 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001468 curproxy->no_options = defproxy.no_options;
1469 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001470 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001471 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001472 curproxy->except_net = defproxy.except_net;
1473 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001474 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001475 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001477 if (defproxy.fwdfor_hdr_len) {
1478 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1479 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1480 }
1481
Willy Tarreaub86db342009-11-30 11:50:16 +01001482 if (defproxy.orgto_hdr_len) {
1483 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1484 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1485 }
1486
Mark Lamourinec2247f02012-01-04 13:02:01 -05001487 if (defproxy.server_id_hdr_len) {
1488 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1489 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1490 }
1491
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 if (curproxy->cap & PR_CAP_FE) {
1493 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001494 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001495 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001496
1497 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001498 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1499 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001500
1501 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001503
Willy Tarreau977b8e42006-12-29 14:19:17 +01001504 if (curproxy->cap & PR_CAP_BE) {
1505 curproxy->fullconn = defproxy.fullconn;
1506 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001508 if (defproxy.check_req) {
1509 curproxy->check_req = calloc(1, defproxy.check_len);
1510 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1511 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001512 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001514 if (defproxy.expect_str) {
1515 curproxy->expect_str = strdup(defproxy.expect_str);
1516 if (defproxy.expect_regex) {
1517 /* note: this regex is known to be valid */
1518 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1519 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1520 }
1521 }
1522
Willy Tarreau67402132012-05-31 20:40:20 +02001523 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 if (defproxy.cookie_name)
1525 curproxy->cookie_name = strdup(defproxy.cookie_name);
1526 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001527 if (defproxy.cookie_domain)
1528 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001529
Willy Tarreau31936852010-10-06 16:59:56 +02001530 if (defproxy.cookie_maxidle)
1531 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1532
1533 if (defproxy.cookie_maxlife)
1534 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1535
Emeric Brun647caf12009-06-30 17:57:00 +02001536 if (defproxy.rdp_cookie_name)
1537 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1538 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1539
Willy Tarreau01732802007-11-01 22:48:15 +01001540 if (defproxy.url_param_name)
1541 curproxy->url_param_name = strdup(defproxy.url_param_name);
1542 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001543
Benoitaffb4812009-03-25 13:02:10 +01001544 if (defproxy.hh_name)
1545 curproxy->hh_name = strdup(defproxy.hh_name);
1546 curproxy->hh_len = defproxy.hh_len;
1547 curproxy->hh_match_domain = defproxy.hh_match_domain;
1548
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001549 if (defproxy.iface_name)
1550 curproxy->iface_name = strdup(defproxy.iface_name);
1551 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001554 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001555 if (defproxy.capture_name)
1556 curproxy->capture_name = strdup(defproxy.capture_name);
1557 curproxy->capture_namelen = defproxy.capture_namelen;
1558 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560
Willy Tarreau977b8e42006-12-29 14:19:17 +01001561 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001562 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001563 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001564 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001565 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001566 curproxy->uri_auth = defproxy.uri_auth;
1567 curproxy->mon_net = defproxy.mon_net;
1568 curproxy->mon_mask = defproxy.mon_mask;
1569 if (defproxy.monitor_uri)
1570 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1571 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001572 if (defproxy.defbe.name)
1573 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001574
1575 /* get either a pointer to the logformat string or a copy of it */
1576 curproxy->logformat_string = defproxy.logformat_string;
1577 if (curproxy->logformat_string &&
1578 curproxy->logformat_string != default_http_log_format &&
1579 curproxy->logformat_string != default_tcp_log_format &&
1580 curproxy->logformat_string != clf_http_log_format)
1581 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001582 }
1583
1584 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001585 curproxy->timeout.connect = defproxy.timeout.connect;
1586 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001587 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001588 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001589 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001590 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001591 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001592 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001593 curproxy->source_addr = defproxy.source_addr;
1594 }
1595
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001597
1598 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001599 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001600 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001601 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001602 LIST_INIT(&node->list);
1603 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1604 }
1605
Willy Tarreau196729e2012-05-31 19:30:26 +02001606 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1607 if (curproxy->uniqueid_format_string)
1608 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001609
1610 /* copy default header unique id */
1611 if (defproxy.header_unique_id)
1612 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1613
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001615 curproxy->conf.used_listener_id = EB_ROOT;
1616 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001617
Willy Tarreau93893792009-07-23 13:19:11 +02001618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001619 }
1620 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1621 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001622 /* FIXME-20070101: we should do this too at the end of the
1623 * config parsing to free all default values.
1624 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001625 free(defproxy.check_req);
1626 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001627 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001628 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001629 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001630 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001631 free(defproxy.capture_name);
1632 free(defproxy.monitor_uri);
1633 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001634 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001635 free(defproxy.fwdfor_hdr_name);
1636 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001637 free(defproxy.orgto_hdr_name);
1638 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001639 free(defproxy.server_id_hdr_name);
1640 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001641 free(defproxy.expect_str);
1642 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001643
Willy Tarreau39b06652012-06-01 10:58:06 +02001644 if (defproxy.logformat_string != default_http_log_format &&
1645 defproxy.logformat_string != default_tcp_log_format &&
1646 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001647 free(defproxy.logformat_string);
1648
1649 free(defproxy.uniqueid_format_string);
1650
Willy Tarreaua534fea2008-08-03 12:19:50 +02001651 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001652 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001653
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 /* we cannot free uri_auth because it might already be used */
1655 init_default_instance();
1656 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001657 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 }
1660 else if (curproxy == NULL) {
1661 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664 }
1665
Willy Tarreau977b8e42006-12-29 14:19:17 +01001666
1667 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001668 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001669 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001670 int cur_arg;
1671
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 if (curproxy == &defproxy) {
1673 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001674 err_code |= ERR_ALERT | ERR_FATAL;
1675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001677 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001678 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001679
Emeric Bruned760922010-10-22 17:59:25 +02001680 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001681 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001682 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001683 err_code |= ERR_ALERT | ERR_FATAL;
1684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001685 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001686
1687 last_listen = curproxy->listen;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001688 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
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) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001701 new_listen->bind_conf = bind_conf;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001702 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001703 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001704 }
1705
Emeric Bruned760922010-10-22 17:59:25 +02001706 /* Set default global rights and owner for unix bind */
1707 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1708 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1709 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001710 cur_arg = 2;
1711 while (*(args[cur_arg])) {
Willy Tarreau26982662012-09-12 23:17:10 +02001712 struct bind_kw *kw;
1713
Willy Tarreau32368ce2012-09-06 11:10:55 +02001714 if (!strcmp(args[cur_arg], "maxconn")) {
1715 struct listener *l;
1716 int val;
1717
1718 if (!*args[cur_arg + 1]) {
1719 Alert("parsing [%s:%d] : '%s' : missing maxconn value.\n",
1720 file, linenum, args[0]);
1721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
1723 }
1724
1725 val = atol(args[cur_arg + 1]);
1726 if (val <= 0) {
1727 Alert("parsing [%s:%d] : '%s' : invalid maxconn value %d, must be > 0.\n",
1728 file, linenum, args[0], val);
1729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
1731 }
1732
1733 for (l = curproxy->listen; l != last_listen; l = l->next)
1734 l->maxconn = val;
1735
1736 cur_arg += 2;
1737 continue;
1738 }
1739
1740 if (!strcmp(args[cur_arg], "backlog")) {
1741 struct listener *l;
1742 int val;
1743
1744 if (!*args[cur_arg + 1]) {
1745 Alert("parsing [%s:%d] : '%s' : missing backlog value.\n",
1746 file, linenum, args[0]);
1747 err_code |= ERR_ALERT | ERR_FATAL;
1748 goto out;
1749 }
1750
1751 val = atol(args[cur_arg + 1]);
1752 if (val <= 0) {
1753 Alert("parsing [%s:%d] : '%s' : invalid backlog value %d, must be > 0.\n",
1754 file, linenum, args[0], val);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
1758
1759 for (l = curproxy->listen; l != last_listen; l = l->next)
1760 l->backlog = val;
1761
1762 cur_arg += 2;
1763 continue;
1764 }
1765
Willy Tarreau50acaaa2012-09-06 14:26:36 +02001766 if (!strcmp(args[cur_arg], "nice")) {
1767 struct listener *l;
1768 int val;
1769
1770 if (!*args[cur_arg + 1]) {
1771 Alert("parsing [%s:%d] : '%s' : missing nice value.\n",
1772 file, linenum, args[0]);
1773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
1775 }
1776
1777 val = atol(args[cur_arg + 1]);
1778 if (val < -1024 || val > 1024) {
1779 Alert("parsing [%s:%d] : '%s' : invalid nice value %d, allowed range is -1024..1024.\n",
1780 file, linenum, args[0], val);
1781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784
1785 for (l = curproxy->listen; l != last_listen; l = l->next)
1786 l->nice = val;
1787
1788 cur_arg += 2;
1789 continue;
1790 }
1791
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001792 if (!strcmp(args[cur_arg], "ssl")) { /* use ssl */
Emeric Brun6e159292012-05-18 16:32:13 +02001793#ifdef USE_OPENSSL
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001794 bind_conf->is_ssl = 1;
Emeric Brunfc0421f2012-09-07 17:30:07 +02001795 cur_arg += 1;
1796 continue;
1797#else
1798 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1799 file, linenum, args[0], args[cur_arg]);
1800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
1802#endif
1803 }
1804
1805 if (!strcmp(args[cur_arg], "crt")) { /* use ssl certificate */
1806#ifdef USE_OPENSSL
1807 if (!*args[cur_arg + 1]) {
1808 Alert("parsing [%s:%d] : '%s' : missing certificate.\n",
1809 file, linenum, args[0]);
1810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
1812 }
1813
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001814 if (ssl_sock_load_cert(args[cur_arg + 1], bind_conf, curproxy) > 0) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02001815 err_code |= ERR_ALERT | ERR_FATAL;
1816 goto out;
1817 }
1818
Emeric Brun6e159292012-05-18 16:32:13 +02001819 cur_arg += 2;
1820 continue;
1821#else
1822 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1823 file, linenum, args[0], args[cur_arg]);
1824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826#endif
1827 }
1828
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001829 if (!strcmp(args[cur_arg], "ciphers")) { /* set cipher suite */
1830#ifdef USE_OPENSSL
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001831 if (!*args[cur_arg + 1]) {
1832 Alert("parsing [%s:%d] : '%s' : missing cipher suite.\n",
1833 file, linenum, args[0]);
1834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
1836 }
1837
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001838 bind_conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001839 cur_arg += 2;
1840 continue;
1841#else
1842 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1843 file, linenum, args[0], args[cur_arg]);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846#endif
1847 }
1848
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001849 if (!strcmp(args[cur_arg], "nosslv3")) { /* disable SSLv3 */
1850#ifdef USE_OPENSSL
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001851 bind_conf->nosslv3 = 1;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001852 cur_arg += 1;
1853 continue;
1854#else
1855 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1856 file, linenum, args[0], args[cur_arg]);
1857 err_code |= ERR_ALERT | ERR_FATAL;
1858 goto out;
1859#endif
1860 }
1861
1862 if (!strcmp(args[cur_arg], "notlsv1")) { /* disable TLSv1 */
1863#ifdef USE_OPENSSL
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001864 bind_conf->notlsv1 = 1;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001865 cur_arg += 1;
1866 continue;
1867#else
1868 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1869 file, linenum, args[0], args[cur_arg]);
1870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
1872#endif
1873 }
1874
David BERARDe566ecb2012-09-04 15:15:13 +02001875 if (!strcmp(args[cur_arg], "prefer-server-ciphers")) { /* Prefert server ciphers */
1876#if defined (USE_OPENSSL) && defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001877 bind_conf->prefer_server_ciphers = 1;
David BERARDe566ecb2012-09-04 15:15:13 +02001878 cur_arg += 1;
1879 continue;
1880#else
1881 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1882 file, linenum, args[0], args[cur_arg]);
1883 err_code |= ERR_ALERT | ERR_FATAL;
1884 goto out;
1885#endif
1886 }
1887
Willy Tarreau8a956912010-10-15 14:27:08 +02001888 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1889 struct listener *l;
1890
1891 for (l = curproxy->listen; l != last_listen; l = l->next)
1892 l->options |= LI_O_ACC_PROXY;
1893
1894 cur_arg ++;
1895 continue;
1896 }
1897
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001898 if (!strcmp(args[cur_arg], "name")) {
1899 struct listener *l;
1900
1901 for (l = curproxy->listen; l != last_listen; l = l->next)
1902 l->name = strdup(args[cur_arg + 1]);
1903
1904 cur_arg += 2;
1905 continue;
1906 }
1907
1908 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001909 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001910 struct listener *l;
1911
1912 if (curproxy->listen->next != last_listen) {
1913 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1914 file, linenum, args[cur_arg]);
1915 err_code |= ERR_ALERT | ERR_FATAL;
1916 goto out;
1917 }
1918
1919 if (!*args[cur_arg + 1]) {
1920 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1921 file, linenum, args[cur_arg]);
1922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
1924 }
1925
1926 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001927 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001928
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001929 if (curproxy->listen->luid <= 0) {
1930 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001931 file, linenum);
1932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
1934 }
1935
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001936 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1937 if (node) {
1938 l = container_of(node, struct listener, conf.id);
1939 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
Willy Tarreau88500de2012-09-13 19:34:38 +02001940 file, linenum, l->luid, args[1], l->bind_conf->file, l->bind_conf->line);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
1943 }
1944 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1945
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001946 cur_arg += 2;
1947 continue;
1948 }
1949
Emeric Bruned760922010-10-22 17:59:25 +02001950 if (!strcmp(args[cur_arg], "mode")) {
1951
1952 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1953 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1954 file, linenum, args[0], args[cur_arg]);
1955 err_code |= ERR_ALERT | ERR_FATAL;
1956 goto out;
1957 }
1958
1959 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1960
1961 cur_arg += 2;
1962 continue;
1963 }
1964
1965 if (!strcmp(args[cur_arg], "uid")) {
1966
1967 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1968 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1969 file, linenum, args[0], args[cur_arg]);
1970 err_code |= ERR_ALERT | ERR_FATAL;
1971 goto out;
1972 }
1973
1974 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1975 cur_arg += 2;
1976 continue;
1977 }
1978
1979 if (!strcmp(args[cur_arg], "gid")) {
1980
1981 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1982 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1983 file, linenum, args[0], args[cur_arg]);
1984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
1986 }
1987
1988 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1989 cur_arg += 2;
1990 continue;
1991 }
1992
1993 if (!strcmp(args[cur_arg], "user")) {
1994 struct passwd *user;
1995
1996 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1997 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1998 file, linenum, args[0], args[cur_arg]);
1999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
2001 }
2002 user = getpwnam(args[cur_arg + 1]);
2003 if (!user) {
2004 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
2005 file, linenum, args[0], args[cur_arg + 1 ]);
2006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
2008 }
2009
2010 curproxy->listen->perm.ux.uid = user->pw_uid;
2011 cur_arg += 2;
2012 continue;
2013 }
2014
2015 if (!strcmp(args[cur_arg], "group")) {
2016 struct group *group;
2017
2018 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2019 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2020 file, linenum, args[0], args[cur_arg]);
2021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
2023 }
2024 group = getgrnam(args[cur_arg + 1]);
2025 if (!group) {
2026 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
2027 file, linenum, args[0], args[cur_arg + 1 ]);
2028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
2030 }
2031
2032 curproxy->listen->perm.ux.gid = group->gr_gid;
2033 cur_arg += 2;
2034 continue;
2035 }
2036
Willy Tarreau26982662012-09-12 23:17:10 +02002037 kw = bind_find_kw(args[cur_arg]);
2038 if (kw) {
2039 char *err = NULL;
2040 int code;
2041
2042 if (!kw->parse) {
2043 Alert("parsing [%s:%d] : '%s' : '%s' option is not implemented in this version (check build options).\n",
2044 file, linenum, args[0], args[cur_arg]);
2045 cur_arg += 1 + kw->skip ;
2046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
2048 }
2049
2050 code = kw->parse(args, cur_arg, curproxy, last_listen, &err);
2051 err_code |= code;
2052
2053 if (code) {
2054 if (err && *err) {
2055 indent_msg(&err, 2);
2056 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err);
2057 }
2058 else
2059 Alert("parsing [%s:%d] : '%s' : error encountered while processing '%s'.\n",
2060 file, linenum, args[0], args[cur_arg]);
2061 if (code & ERR_FATAL) {
2062 free(err);
2063 cur_arg += 1 + kw->skip;
2064 goto out;
2065 }
2066 }
2067 free(err);
2068 cur_arg += 1 + kw->skip;
2069 continue;
2070 }
2071
Willy Tarreaub48f9582011-09-05 01:17:06 +02002072 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 +01002073 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002076 }
Willy Tarreau93893792009-07-23 13:19:11 +02002077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078 }
2079 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2080 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2081 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2082 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002086 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002087 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002088
Willy Tarreaubaaee002006-06-26 02:48:02 +02002089 /* flush useless bits */
2090 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002093 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002094 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002095 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002096
Willy Tarreau1c47f852006-07-09 08:22:27 +02002097 if (!*args[1]) {
2098 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2099 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002102 }
2103
Willy Tarreaua534fea2008-08-03 12:19:50 +02002104 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002105 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002106 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002107 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002108 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2109
Willy Tarreau93893792009-07-23 13:19:11 +02002110 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2113 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2114 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2115 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2116 else {
2117 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002118 err_code |= ERR_ALERT | ERR_FATAL;
2119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 }
2121 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002122 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002123 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002124
2125 if (curproxy == &defproxy) {
2126 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2127 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002128 err_code |= ERR_ALERT | ERR_FATAL;
2129 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002130 }
2131
2132 if (!*args[1]) {
2133 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2134 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002137 }
2138
2139 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002140 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002141
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002142 if (curproxy->uuid <= 0) {
2143 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002144 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002145 err_code |= ERR_ALERT | ERR_FATAL;
2146 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002147 }
2148
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002149 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2150 if (node) {
2151 struct proxy *target = container_of(node, struct proxy, conf.id);
2152 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2153 file, linenum, proxy_type_str(curproxy), curproxy->id,
2154 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
2157 }
2158 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002159 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002160 else if (!strcmp(args[0], "description")) {
2161 int i, len=0;
2162 char *d;
2163
Cyril Bonté99ed3272010-01-24 23:29:44 +01002164 if (curproxy == &defproxy) {
2165 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2166 file, linenum, args[0]);
2167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
2169 }
2170
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002171 if (!*args[1]) {
2172 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2173 file, linenum, args[0]);
2174 return -1;
2175 }
2176
2177 for(i=1; *args[i]; i++)
2178 len += strlen(args[i])+1;
2179
2180 d = (char *)calloc(1, len);
2181 curproxy->desc = d;
2182
2183 d += sprintf(d, "%s", args[1]);
2184 for(i=2; *args[i]; i++)
2185 d += sprintf(d, " %s", args[i]);
2186
2187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002188 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2189 curproxy->state = PR_STSTOPPED;
2190 }
2191 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2192 curproxy->state = PR_STNEW;
2193 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002194 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2195 int cur_arg = 1;
2196 unsigned int set = 0;
2197
2198 while (*args[cur_arg]) {
2199 int u;
2200 if (strcmp(args[cur_arg], "all") == 0) {
2201 set = 0;
2202 break;
2203 }
2204 else if (strcmp(args[cur_arg], "odd") == 0) {
2205 set |= 0x55555555;
2206 }
2207 else if (strcmp(args[cur_arg], "even") == 0) {
2208 set |= 0xAAAAAAAA;
2209 }
2210 else {
2211 u = str2uic(args[cur_arg]);
2212 if (u < 1 || u > 32) {
2213 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2214 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002217 }
2218 if (u > global.nbproc) {
2219 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2220 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002221 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002222 }
2223 set |= 1 << (u - 1);
2224 }
2225 cur_arg++;
2226 }
2227 curproxy->bind_proc = set;
2228 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002229 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002230 if (curproxy == &defproxy) {
2231 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002234 }
2235
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002236 err = invalid_char(args[1]);
2237 if (err) {
2238 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2239 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002240 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002241 }
2242
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002243 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2244 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2245 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002248 }
2249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2251 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252
Willy Tarreau977b8e42006-12-29 14:19:17 +01002253 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002255
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 if (*(args[1]) == 0) {
2257 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2258 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002262
Willy Tarreau67402132012-05-31 20:40:20 +02002263 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002264 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002265 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002266 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 curproxy->cookie_name = strdup(args[1]);
2268 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002269
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 cur_arg = 2;
2271 while (*(args[cur_arg])) {
2272 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002273 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 }
2275 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002276 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 }
2278 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002279 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 }
2281 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002282 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 }
2284 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002285 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002287 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002288 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002291 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002293 else if (!strcmp(args[cur_arg], "httponly")) {
2294 curproxy->ck_opts |= PR_CK_HTTPONLY;
2295 }
2296 else if (!strcmp(args[cur_arg], "secure")) {
2297 curproxy->ck_opts |= PR_CK_SECURE;
2298 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002299 else if (!strcmp(args[cur_arg], "domain")) {
2300 if (!*args[cur_arg + 1]) {
2301 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2302 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002305 }
2306
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002307 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002308 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002309 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2310 " dots nor does not start with a dot."
2311 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002312 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002313 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002314 }
2315
2316 err = invalid_domainchar(args[cur_arg + 1]);
2317 if (err) {
2318 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2319 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002322 }
2323
Willy Tarreau68a897b2009-12-03 23:28:34 +01002324 if (!curproxy->cookie_domain) {
2325 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2326 } else {
2327 /* one domain was already specified, add another one by
2328 * building the string which will be returned along with
2329 * the cookie.
2330 */
2331 char *new_ptr;
2332 int new_len = strlen(curproxy->cookie_domain) +
2333 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2334 new_ptr = malloc(new_len);
2335 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2336 free(curproxy->cookie_domain);
2337 curproxy->cookie_domain = new_ptr;
2338 }
Willy Tarreau31936852010-10-06 16:59:56 +02002339 cur_arg++;
2340 }
2341 else if (!strcmp(args[cur_arg], "maxidle")) {
2342 unsigned int maxidle;
2343 const char *res;
2344
2345 if (!*args[cur_arg + 1]) {
2346 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2347 file, linenum, args[cur_arg]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
2351
2352 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2353 if (res) {
2354 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2355 file, linenum, *res, args[cur_arg]);
2356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
2358 }
2359 curproxy->cookie_maxidle = maxidle;
2360 cur_arg++;
2361 }
2362 else if (!strcmp(args[cur_arg], "maxlife")) {
2363 unsigned int maxlife;
2364 const char *res;
2365
2366 if (!*args[cur_arg + 1]) {
2367 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2368 file, linenum, args[cur_arg]);
2369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
2371 }
2372
2373 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2374 if (res) {
2375 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2376 file, linenum, *res, args[cur_arg]);
2377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
2379 }
2380 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002381 cur_arg++;
2382 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002384 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 +02002385 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 }
2389 cur_arg++;
2390 }
Willy Tarreau67402132012-05-31 20:40:20 +02002391 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2393 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
2396
Willy Tarreau67402132012-05-31 20:40:20 +02002397 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2399 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002402
Willy Tarreau67402132012-05-31 20:40:20 +02002403 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002404 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2405 file, linenum);
2406 err_code |= ERR_ALERT | ERR_FATAL;
2407 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002409 else if (!strcmp(args[0], "persist")) { /* persist */
2410 if (*(args[1]) == 0) {
2411 Alert("parsing [%s:%d] : missing persist method.\n",
2412 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002415 }
2416
2417 if (!strncmp(args[1], "rdp-cookie", 10)) {
2418 curproxy->options2 |= PR_O2_RDPC_PRST;
2419
Emeric Brunb982a3d2010-01-04 15:45:53 +01002420 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002421 const char *beg, *end;
2422
2423 beg = args[1] + 11;
2424 end = strchr(beg, ')');
2425
2426 if (!end || end == beg) {
2427 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2428 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002431 }
2432
2433 free(curproxy->rdp_cookie_name);
2434 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2435 curproxy->rdp_cookie_len = end-beg;
2436 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002437 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002438 free(curproxy->rdp_cookie_name);
2439 curproxy->rdp_cookie_name = strdup("msts");
2440 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2441 }
2442 else { /* syntax */
2443 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2444 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002447 }
2448 }
2449 else {
2450 Alert("parsing [%s:%d] : unknown persist method.\n",
2451 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002454 }
2455 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002457 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002459 if (curproxy == &defproxy) {
2460 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
Willy Tarreau977b8e42006-12-29 14:19:17 +01002465 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002467
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002469 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 }
2474 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002475 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 curproxy->appsession_name = strdup(args[1]);
2477 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2478 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002479 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2480 if (err) {
2481 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2482 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002485 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002486 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002487
Willy Tarreau51041c72007-09-09 21:56:53 +02002488 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2489 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_ABORT;
2491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002492 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002493
2494 cur_arg = 6;
2495 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002496 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2497 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002498 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002499 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002500 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002501 } else if (!strcmp(args[cur_arg], "prefix")) {
2502 curproxy->options2 |= PR_O2_AS_PFX;
2503 } else if (!strcmp(args[cur_arg], "mode")) {
2504 if (!*args[cur_arg + 1]) {
2505 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2506 file, linenum, args[0], args[cur_arg]);
2507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
2509 }
2510
2511 cur_arg++;
2512 if (!strcmp(args[cur_arg], "query-string")) {
2513 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2514 curproxy->options2 |= PR_O2_AS_M_QS;
2515 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2516 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2517 curproxy->options2 |= PR_O2_AS_M_PP;
2518 } else {
2519 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
2522 }
2523 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002524 cur_arg++;
2525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 } /* Url App Session */
2527 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002528 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002530
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002532 if (curproxy == &defproxy) {
2533 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
2536 }
2537
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 if (*(args[4]) == 0) {
2539 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2540 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002544 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 curproxy->capture_name = strdup(args[2]);
2546 curproxy->capture_namelen = strlen(curproxy->capture_name);
2547 curproxy->capture_len = atol(args[4]);
2548 if (curproxy->capture_len >= CAPTURE_LEN) {
2549 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2550 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 curproxy->capture_len = CAPTURE_LEN - 1;
2553 }
2554 curproxy->to_log |= LW_COOKIE;
2555 }
2556 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2557 struct cap_hdr *hdr;
2558
2559 if (curproxy == &defproxy) {
2560 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 +02002561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 }
2564
2565 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2566 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2567 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_FATAL;
2569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 }
2571
2572 hdr = calloc(sizeof(struct cap_hdr), 1);
2573 hdr->next = curproxy->req_cap;
2574 hdr->name = strdup(args[3]);
2575 hdr->namelen = strlen(args[3]);
2576 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002577 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 hdr->index = curproxy->nb_req_cap++;
2579 curproxy->req_cap = hdr;
2580 curproxy->to_log |= LW_REQHDR;
2581 }
2582 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2583 struct cap_hdr *hdr;
2584
2585 if (curproxy == &defproxy) {
2586 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 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 }
2590
2591 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2592 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2593 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
2597 hdr = calloc(sizeof(struct cap_hdr), 1);
2598 hdr->next = curproxy->rsp_cap;
2599 hdr->name = strdup(args[3]);
2600 hdr->namelen = strlen(args[3]);
2601 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002602 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 hdr->index = curproxy->nb_rsp_cap++;
2604 curproxy->rsp_cap = hdr;
2605 curproxy->to_log |= LW_RSPHDR;
2606 }
2607 else {
2608 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 }
2613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002615 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002616 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002617
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 if (*(args[1]) == 0) {
2619 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\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 }
2624 curproxy->conn_retries = atol(args[1]);
2625 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002626 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002627 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002628
2629 if (curproxy == &defproxy) {
2630 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
2633 }
2634
Willy Tarreauff011f22011-01-06 17:51:27 +01002635 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 +01002636 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2637 file, linenum, args[0]);
2638 err_code |= ERR_WARN;
2639 }
2640
Willy Tarreauff011f22011-01-06 17:51:27 +01002641 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002642
Willy Tarreauff011f22011-01-06 17:51:27 +01002643 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002644 err_code |= ERR_ALERT | ERR_ABORT;
2645 goto out;
2646 }
2647
Willy Tarreauff011f22011-01-06 17:51:27 +01002648 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2649 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002650 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002651 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2652 /* set the header name and length into the proxy structure */
2653 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2654 err_code |= ERR_WARN;
2655
2656 if (!*args[1]) {
2657 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2658 file, linenum, args[0]);
2659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
2661 }
2662
2663 /* set the desired header name */
2664 free(curproxy->server_id_hdr_name);
2665 curproxy->server_id_hdr_name = strdup(args[1]);
2666 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2667 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002668 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002669 if (curproxy == &defproxy) {
2670 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002673 }
2674
Willy Tarreauef6494c2010-01-28 17:12:36 +01002675 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002676 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2677 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002680 }
2681
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002682 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2683 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2684 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002687 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002688
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002689 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002690 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002691 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002692 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002693 struct redirect_rule *rule;
2694 int cur_arg;
2695 int type = REDIRECT_TYPE_NONE;
2696 int code = 302;
2697 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002698 char *cookie = NULL;
2699 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002700 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002701
Cyril Bonté99ed3272010-01-24 23:29:44 +01002702 if (curproxy == &defproxy) {
2703 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
2706 }
2707
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002708 cur_arg = 1;
2709 while (*(args[cur_arg])) {
2710 if (!strcmp(args[cur_arg], "location")) {
2711 if (!*args[cur_arg + 1]) {
2712 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2713 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002716 }
2717
2718 type = REDIRECT_TYPE_LOCATION;
2719 cur_arg++;
2720 destination = args[cur_arg];
2721 }
2722 else if (!strcmp(args[cur_arg], "prefix")) {
2723 if (!*args[cur_arg + 1]) {
2724 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2725 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002728 }
2729
2730 type = REDIRECT_TYPE_PREFIX;
2731 cur_arg++;
2732 destination = args[cur_arg];
2733 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002734 else if (!strcmp(args[cur_arg], "scheme")) {
2735 if (!*args[cur_arg + 1]) {
2736 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2737 file, linenum, args[0], args[cur_arg]);
2738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
2740 }
2741
2742 type = REDIRECT_TYPE_SCHEME;
2743 cur_arg++;
2744 destination = args[cur_arg];
2745 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002746 else if (!strcmp(args[cur_arg], "set-cookie")) {
2747 if (!*args[cur_arg + 1]) {
2748 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2749 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002752 }
2753
2754 cur_arg++;
2755 cookie = args[cur_arg];
2756 cookie_set = 1;
2757 }
2758 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2759 if (!*args[cur_arg + 1]) {
2760 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2761 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002764 }
2765
2766 cur_arg++;
2767 cookie = args[cur_arg];
2768 cookie_set = 0;
2769 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002770 else if (!strcmp(args[cur_arg],"code")) {
2771 if (!*args[cur_arg + 1]) {
2772 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2773 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002776 }
2777 cur_arg++;
2778 code = atol(args[cur_arg]);
2779 if (code < 301 || code > 303) {
2780 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2781 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002784 }
2785 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002786 else if (!strcmp(args[cur_arg],"drop-query")) {
2787 flags |= REDIRECT_FLAG_DROP_QS;
2788 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002789 else if (!strcmp(args[cur_arg],"append-slash")) {
2790 flags |= REDIRECT_FLAG_APPEND_SLASH;
2791 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002792 else if (strcmp(args[cur_arg], "if") == 0 ||
2793 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002794 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002795 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002796 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2797 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
2800 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002801 break;
2802 }
2803 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002804 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002805 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 cur_arg++;
2810 }
2811
2812 if (type == REDIRECT_TYPE_NONE) {
2813 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2814 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002817 }
2818
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002819 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2820 rule->cond = cond;
2821 rule->rdr_str = strdup(destination);
2822 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002823 if (cookie) {
2824 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002825 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002826 */
2827 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002828 if (cookie_set) {
2829 rule->cookie_str = malloc(rule->cookie_len + 10);
2830 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2831 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2832 rule->cookie_len += 9;
2833 } else {
2834 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002835 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002836 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2837 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002838 }
2839 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002840 rule->type = type;
2841 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002842 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002843 LIST_INIT(&rule->list);
2844 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002845 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2846 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002847 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002848 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002849 struct switching_rule *rule;
2850
Willy Tarreaub099aca2008-10-12 17:26:37 +02002851 if (curproxy == &defproxy) {
2852 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002855 }
2856
Willy Tarreau55ea7572007-06-17 19:56:27 +02002857 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002859
2860 if (*(args[1]) == 0) {
2861 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002864 }
2865
Willy Tarreauef6494c2010-01-28 17:12:36 +01002866 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002867 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2868 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002871 }
2872
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002873 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2874 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2875 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002878 }
2879
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002880 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002881
Willy Tarreau55ea7572007-06-17 19:56:27 +02002882 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2883 rule->cond = cond;
2884 rule->be.name = strdup(args[1]);
2885 LIST_INIT(&rule->list);
2886 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2887 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002888 else if (strcmp(args[0], "use-server") == 0) {
2889 struct server_rule *rule;
2890
2891 if (curproxy == &defproxy) {
2892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
2896
2897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2898 err_code |= ERR_WARN;
2899
2900 if (*(args[1]) == 0) {
2901 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905
2906 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2907 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2908 file, linenum, args[0]);
2909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
2911 }
2912
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002913 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2914 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2915 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
2918 }
2919
2920 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2921
2922 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2923 rule->cond = cond;
2924 rule->srv.name = strdup(args[1]);
2925 LIST_INIT(&rule->list);
2926 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2927 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2928 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002929 else if ((!strcmp(args[0], "force-persist")) ||
2930 (!strcmp(args[0], "ignore-persist"))) {
2931 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002932
2933 if (curproxy == &defproxy) {
2934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937 }
2938
2939 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2940 err_code |= ERR_WARN;
2941
Willy Tarreauef6494c2010-01-28 17:12:36 +01002942 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002943 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2944 file, linenum, args[0]);
2945 err_code |= ERR_ALERT | ERR_FATAL;
2946 goto out;
2947 }
2948
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002949 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2950 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2951 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
2954 }
2955
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002956 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002957
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002958 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002959 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002960 if (!strcmp(args[0], "force-persist")) {
2961 rule->type = PERSIST_TYPE_FORCE;
2962 } else {
2963 rule->type = PERSIST_TYPE_IGNORE;
2964 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002965 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002966 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002967 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002968 else if (!strcmp(args[0], "stick-table")) {
2969 int myidx = 1;
2970
Emeric Brun32da3c42010-09-23 18:39:19 +02002971 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002972 curproxy->table.type = (unsigned int)-1;
2973 while (*args[myidx]) {
2974 const char *err;
2975
2976 if (strcmp(args[myidx], "size") == 0) {
2977 myidx++;
2978 if (!*(args[myidx])) {
2979 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2980 file, linenum, args[myidx-1]);
2981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
2983 }
2984 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2985 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2986 file, linenum, *err, args[myidx-1]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002990 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002991 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002992 else if (strcmp(args[myidx], "peers") == 0) {
2993 myidx++;
2994 if (!*(args[myidx])) {
2995 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2996 file, linenum, args[myidx-1]);
2997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
2999 }
3000 curproxy->table.peers.name = strdup(args[myidx++]);
3001 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003002 else if (strcmp(args[myidx], "expire") == 0) {
3003 myidx++;
3004 if (!*(args[myidx])) {
3005 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3006 file, linenum, args[myidx-1]);
3007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
3009 }
3010 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3011 if (err) {
3012 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3013 file, linenum, *err, args[myidx-1]);
3014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
3016 }
3017 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003018 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003019 }
3020 else if (strcmp(args[myidx], "nopurge") == 0) {
3021 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003022 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003023 }
3024 else if (strcmp(args[myidx], "type") == 0) {
3025 myidx++;
3026 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3027 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3028 file, linenum, args[myidx]);
3029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
3031 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003032 /* myidx already points to next arg */
3033 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003034 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003035 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003036 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003037
3038 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003039 nw = args[myidx];
3040 while (*nw) {
3041 /* the "store" keyword supports a comma-separated list */
3042 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003043 sa = NULL; /* store arg */
3044 while (*nw && *nw != ',') {
3045 if (*nw == '(') {
3046 *nw = 0;
3047 sa = ++nw;
3048 while (*nw != ')') {
3049 if (!*nw) {
3050 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3051 file, linenum, args[0], cw);
3052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
3054 }
3055 nw++;
3056 }
3057 *nw = '\0';
3058 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003059 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003060 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003061 if (*nw)
3062 *nw++ = '\0';
3063 type = stktable_get_data_type(cw);
3064 if (type < 0) {
3065 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3066 file, linenum, args[0], cw);
3067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
3069 }
Willy Tarreauac782882010-06-20 10:41:54 +02003070
3071 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3072 switch (err) {
3073 case PE_NONE: break;
3074 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003075 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3076 file, linenum, args[0], cw);
3077 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003078 break;
3079
3080 case PE_ARG_MISSING:
3081 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3082 file, linenum, args[0], cw);
3083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
3085
3086 case PE_ARG_NOT_USED:
3087 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3088 file, linenum, args[0], cw);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091
3092 default:
3093 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3094 file, linenum, args[0], cw);
3095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003097 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003098 }
3099 myidx++;
3100 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003101 else {
3102 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3103 file, linenum, args[myidx]);
3104 err_code |= ERR_ALERT | ERR_FATAL;
3105 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003106 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003107 }
3108
3109 if (!curproxy->table.size) {
3110 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3111 file, linenum);
3112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
3114 }
3115
3116 if (curproxy->table.type == (unsigned int)-1) {
3117 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3118 file, linenum);
3119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
3121 }
3122 }
3123 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003124 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003125 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003126 int myidx = 0;
3127 const char *name = NULL;
3128 int flags;
3129
3130 if (curproxy == &defproxy) {
3131 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
3134 }
3135
3136 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3137 err_code |= ERR_WARN;
3138 goto out;
3139 }
3140
3141 myidx++;
3142 if ((strcmp(args[myidx], "store") == 0) ||
3143 (strcmp(args[myidx], "store-request") == 0)) {
3144 myidx++;
3145 flags = STK_IS_STORE;
3146 }
3147 else if (strcmp(args[myidx], "store-response") == 0) {
3148 myidx++;
3149 flags = STK_IS_STORE | STK_ON_RSP;
3150 }
3151 else if (strcmp(args[myidx], "match") == 0) {
3152 myidx++;
3153 flags = STK_IS_MATCH;
3154 }
3155 else if (strcmp(args[myidx], "on") == 0) {
3156 myidx++;
3157 flags = STK_IS_MATCH | STK_IS_STORE;
3158 }
3159 else {
3160 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
3164
3165 if (*(args[myidx]) == 0) {
3166 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
3169 }
3170
David du Colombier7af46052012-05-16 14:16:48 +02003171 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003172 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003173 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
3176 }
3177
3178 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003179 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003180 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3181 file, linenum, args[0], expr->fetch->kw);
3182 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003183 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003184 goto out;
3185 }
3186 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003187 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003188 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3189 file, linenum, args[0], expr->fetch->kw);
3190 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003191 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003192 goto out;
3193 }
3194 }
3195
3196 if (strcmp(args[myidx], "table") == 0) {
3197 myidx++;
3198 name = args[myidx++];
3199 }
3200
Willy Tarreauef6494c2010-01-28 17:12:36 +01003201 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003202 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3203 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3204 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003205 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003206 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003207 goto out;
3208 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003209 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003210 else if (*(args[myidx])) {
3211 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3212 file, linenum, args[0], args[myidx]);
3213 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003214 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003215 goto out;
3216 }
Emeric Brun97679e72010-09-23 17:56:44 +02003217 if (flags & STK_ON_RSP)
3218 err_code |= warnif_cond_requires_req(cond, file, linenum);
3219 else
3220 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003221
Emeric Brunb982a3d2010-01-04 15:45:53 +01003222 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3223 rule->cond = cond;
3224 rule->expr = expr;
3225 rule->flags = flags;
3226 rule->table.name = name ? strdup(name) : NULL;
3227 LIST_INIT(&rule->list);
3228 if (flags & STK_ON_RSP)
3229 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3230 else
3231 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3232 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003234 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003236
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3238 curproxy->uri_auth = NULL; /* we must detach from the default config */
3239
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003240 if (!*args[1]) {
3241 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003242 } else if (!strcmp(args[1], "admin")) {
3243 struct stats_admin_rule *rule;
3244
3245 if (curproxy == &defproxy) {
3246 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
3250
3251 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3252 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3253 err_code |= ERR_ALERT | ERR_ABORT;
3254 goto out;
3255 }
3256
3257 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3258 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3259 file, linenum, args[0], args[1]);
3260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
3262 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003263 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3264 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3265 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
3268 }
3269
3270 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3271
3272 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3273 rule->cond = cond;
3274 LIST_INIT(&rule->list);
3275 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 } else if (!strcmp(args[1], "uri")) {
3277 if (*(args[2]) == 0) {
3278 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3282 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003283 err_code |= ERR_ALERT | ERR_ABORT;
3284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 }
3286 } else if (!strcmp(args[1], "realm")) {
3287 if (*(args[2]) == 0) {
3288 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3292 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_ABORT;
3294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003296 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003297 unsigned interval;
3298
3299 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3300 if (err) {
3301 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3302 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003305 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3306 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_ALERT | ERR_ABORT;
3308 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003309 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003310 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003311 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003312
3313 if (curproxy == &defproxy) {
3314 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
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
Willy Tarreauff011f22011-01-06 17:51:27 +01003325 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3326 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003327 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3328 file, linenum, args[0]);
3329 err_code |= ERR_WARN;
3330 }
3331
Willy Tarreauff011f22011-01-06 17:51:27 +01003332 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003333
Willy Tarreauff011f22011-01-06 17:51:27 +01003334 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003335 err_code |= ERR_ALERT | ERR_ABORT;
3336 goto out;
3337 }
3338
Willy Tarreauff011f22011-01-06 17:51:27 +01003339 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3340 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003341
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 } else if (!strcmp(args[1], "auth")) {
3343 if (*(args[2]) == 0) {
3344 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3348 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_ALERT | ERR_ABORT;
3350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 }
3352 } else if (!strcmp(args[1], "scope")) {
3353 if (*(args[2]) == 0) {
3354 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003355 err_code |= ERR_ALERT | ERR_FATAL;
3356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3358 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_ALERT | ERR_ABORT;
3360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 }
3362 } else if (!strcmp(args[1], "enable")) {
3363 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3364 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_ALERT | ERR_ABORT;
3366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003368 } else if (!strcmp(args[1], "hide-version")) {
3369 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3370 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_ABORT;
3372 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003373 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003374 } else if (!strcmp(args[1], "show-legends")) {
3375 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3376 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3377 err_code |= ERR_ALERT | ERR_ABORT;
3378 goto out;
3379 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003380 } else if (!strcmp(args[1], "show-node")) {
3381
3382 if (*args[2]) {
3383 int i;
3384 char c;
3385
3386 for (i=0; args[2][i]; i++) {
3387 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003388 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3389 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003390 break;
3391 }
3392
3393 if (!i || args[2][i]) {
3394 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3395 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3396 file, linenum, args[0], args[1]);
3397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
3400 }
3401
3402 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3403 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3404 err_code |= ERR_ALERT | ERR_ABORT;
3405 goto out;
3406 }
3407 } else if (!strcmp(args[1], "show-desc")) {
3408 char *desc = NULL;
3409
3410 if (*args[2]) {
3411 int i, len=0;
3412 char *d;
3413
3414 for(i=2; *args[i]; i++)
3415 len += strlen(args[i])+1;
3416
3417 desc = d = (char *)calloc(1, len);
3418
3419 d += sprintf(d, "%s", args[2]);
3420 for(i=3; *args[i]; i++)
3421 d += sprintf(d, " %s", args[i]);
3422 }
3423
3424 if (!*args[2] && !global.desc)
3425 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3426 file, linenum, args[1]);
3427 else {
3428 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3429 free(desc);
3430 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3431 err_code |= ERR_ALERT | ERR_ABORT;
3432 goto out;
3433 }
3434 free(desc);
3435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003437stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003438 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 +01003439 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 }
3443 }
3444 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003445 int optnum;
3446
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003447 if (*(args[1]) == '\0') {
3448 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3449 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003453
3454 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3455 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003456 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3457 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3458 file, linenum, cfg_opts[optnum].name);
3459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
3461 }
Willy Tarreau93893792009-07-23 13:19:11 +02003462 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3463 err_code |= ERR_WARN;
3464 goto out;
3465 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003466
Willy Tarreau3842f002009-06-14 11:39:52 +02003467 curproxy->no_options &= ~cfg_opts[optnum].val;
3468 curproxy->options &= ~cfg_opts[optnum].val;
3469
3470 switch (kwm) {
3471 case KWM_STD:
3472 curproxy->options |= cfg_opts[optnum].val;
3473 break;
3474 case KWM_NO:
3475 curproxy->no_options |= cfg_opts[optnum].val;
3476 break;
3477 case KWM_DEF: /* already cleared */
3478 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003479 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003480
Willy Tarreau93893792009-07-23 13:19:11 +02003481 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003482 }
3483 }
3484
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003485 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3486 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003487 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3488 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3489 file, linenum, cfg_opts2[optnum].name);
3490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
3492 }
Willy Tarreau93893792009-07-23 13:19:11 +02003493 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3494 err_code |= ERR_WARN;
3495 goto out;
3496 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003497
Willy Tarreau3842f002009-06-14 11:39:52 +02003498 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3499 curproxy->options2 &= ~cfg_opts2[optnum].val;
3500
3501 switch (kwm) {
3502 case KWM_STD:
3503 curproxy->options2 |= cfg_opts2[optnum].val;
3504 break;
3505 case KWM_NO:
3506 curproxy->no_options2 |= cfg_opts2[optnum].val;
3507 break;
3508 case KWM_DEF: /* already cleared */
3509 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003510 }
Willy Tarreau93893792009-07-23 13:19:11 +02003511 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003512 }
3513 }
3514
Willy Tarreau3842f002009-06-14 11:39:52 +02003515 if (kwm != KWM_STD) {
3516 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003517 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003520 }
3521
Emeric Brun3a058f32009-06-30 18:26:00 +02003522 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003523 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003525 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003526 if (*(args[2]) != '\0') {
3527 if (!strcmp(args[2], "clf")) {
3528 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003529 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003530 } else {
3531 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003534 }
3535 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003536 if (curproxy->logformat_string != default_http_log_format &&
3537 curproxy->logformat_string != default_tcp_log_format &&
3538 curproxy->logformat_string != clf_http_log_format)
3539 free(curproxy->logformat_string);
3540 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003541 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003542 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003544 if (curproxy->logformat_string != default_http_log_format &&
3545 curproxy->logformat_string != default_tcp_log_format &&
3546 curproxy->logformat_string != clf_http_log_format)
3547 free(curproxy->logformat_string);
3548 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 else if (!strcmp(args[1], "tcpka")) {
3551 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003552 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003554
3555 if (curproxy->cap & PR_CAP_FE)
3556 curproxy->options |= PR_O_TCP_CLI_KA;
3557 if (curproxy->cap & PR_CAP_BE)
3558 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 }
3560 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003561 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003562 err_code |= ERR_WARN;
3563
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003565 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003566 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003567 curproxy->options2 &= ~PR_O2_CHK_ANY;
3568 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 if (!*args[2]) { /* no argument */
3570 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3571 curproxy->check_len = strlen(DEF_CHECK_REQ);
3572 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003573 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574 curproxy->check_req = (char *)malloc(reqlen);
3575 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003576 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003578 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 if (*args[4])
3580 reqlen += strlen(args[4]);
3581 else
3582 reqlen += strlen("HTTP/1.0");
3583
3584 curproxy->check_req = (char *)malloc(reqlen);
3585 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003586 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003588 }
3589 else if (!strcmp(args[1], "ssl-hello-chk")) {
3590 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003591 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003592 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003593
Willy Tarreaua534fea2008-08-03 12:19:50 +02003594 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003595 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003596 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003597 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 }
Willy Tarreau23677902007-05-08 23:50:35 +02003599 else if (!strcmp(args[1], "smtpchk")) {
3600 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003601 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003602 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003603 curproxy->options2 &= ~PR_O2_CHK_ANY;
3604 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003605
3606 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3607 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3608 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3609 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3610 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3611 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3612 curproxy->check_req = (char *)malloc(reqlen);
3613 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3614 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3615 } else {
3616 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3617 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3618 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3619 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3620 }
3621 }
3622 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003623 else if (!strcmp(args[1], "pgsql-check")) {
3624 /* use PostgreSQL request to check servers' health */
3625 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3626 err_code |= ERR_WARN;
3627
3628 free(curproxy->check_req);
3629 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003630 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003631 curproxy->options2 |= PR_O2_PGSQL_CHK;
3632
3633 if (*(args[2])) {
3634 int cur_arg = 2;
3635
3636 while (*(args[cur_arg])) {
3637 if (strcmp(args[cur_arg], "user") == 0) {
3638 char * packet;
3639 uint32_t packet_len;
3640 uint32_t pv;
3641
3642 /* suboption header - needs additional argument for it */
3643 if (*(args[cur_arg+1]) == 0) {
3644 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3645 file, linenum, args[0], args[1], args[cur_arg]);
3646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
3648 }
3649
3650 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3651 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3652 pv = htonl(0x30000); /* protocol version 3.0 */
3653
3654 packet = (char*) calloc(1, packet_len);
3655
3656 memcpy(packet + 4, &pv, 4);
3657
3658 /* copy "user" */
3659 memcpy(packet + 8, "user", 4);
3660
3661 /* copy username */
3662 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3663
3664 free(curproxy->check_req);
3665 curproxy->check_req = packet;
3666 curproxy->check_len = packet_len;
3667
3668 packet_len = htonl(packet_len);
3669 memcpy(packet, &packet_len, 4);
3670 cur_arg += 2;
3671 } else {
3672 /* unknown suboption - catchall */
3673 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3674 file, linenum, args[0], args[1]);
3675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
3677 }
3678 } /* end while loop */
3679 }
3680 }
3681
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003682 else if (!strcmp(args[1], "redis-check")) {
3683 /* use REDIS PING request to check servers' health */
3684 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3685 err_code |= ERR_WARN;
3686
3687 free(curproxy->check_req);
3688 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003689 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003690 curproxy->options2 |= PR_O2_REDIS_CHK;
3691
3692 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3693 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3694 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3695 }
3696
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003697 else if (!strcmp(args[1], "mysql-check")) {
3698 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003699 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3700 err_code |= ERR_WARN;
3701
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003702 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003703 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003704 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003705 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003706
3707 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3708 * const char mysql40_client_auth_pkt[] = {
3709 * "\x0e\x00\x00" // packet length
3710 * "\x01" // packet number
3711 * "\x00\x00" // client capabilities
3712 * "\x00\x00\x01" // max packet
3713 * "haproxy\x00" // username (null terminated string)
3714 * "\x00" // filler (always 0x00)
3715 * "\x01\x00\x00" // packet length
3716 * "\x00" // packet number
3717 * "\x01" // COM_QUIT command
3718 * };
3719 */
3720
3721 if (*(args[2])) {
3722 int cur_arg = 2;
3723
3724 while (*(args[cur_arg])) {
3725 if (strcmp(args[cur_arg], "user") == 0) {
3726 char *mysqluser;
3727 int packetlen, reqlen, userlen;
3728
3729 /* suboption header - needs additional argument for it */
3730 if (*(args[cur_arg+1]) == 0) {
3731 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3732 file, linenum, args[0], args[1], args[cur_arg]);
3733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
3735 }
3736 mysqluser = args[cur_arg + 1];
3737 userlen = strlen(mysqluser);
3738 packetlen = userlen + 7;
3739 reqlen = packetlen + 9;
3740
3741 free(curproxy->check_req);
3742 curproxy->check_req = (char *)calloc(1, reqlen);
3743 curproxy->check_len = reqlen;
3744
3745 snprintf(curproxy->check_req, 4, "%c%c%c",
3746 ((unsigned char) packetlen & 0xff),
3747 ((unsigned char) (packetlen >> 8) & 0xff),
3748 ((unsigned char) (packetlen >> 16) & 0xff));
3749
3750 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003751 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003752 curproxy->check_req[8] = 1;
3753 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3754 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3755 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3756 cur_arg += 2;
3757 } else {
3758 /* unknown suboption - catchall */
3759 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3760 file, linenum, args[0], args[1]);
3761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
3763 }
3764 } /* end while loop */
3765 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003766 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003767 else if (!strcmp(args[1], "ldap-check")) {
3768 /* use LDAP request to check servers' health */
3769 free(curproxy->check_req);
3770 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003771 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003772 curproxy->options2 |= PR_O2_LDAP_CHK;
3773
3774 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3775 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3776 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3777 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003778 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003779 int cur_arg;
3780
3781 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3782 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003783 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003784
Willy Tarreau87cf5142011-08-19 22:57:24 +02003785 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003786
3787 free(curproxy->fwdfor_hdr_name);
3788 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3789 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3790
3791 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3792 cur_arg = 2;
3793 while (*(args[cur_arg])) {
3794 if (!strcmp(args[cur_arg], "except")) {
3795 /* suboption except - needs additional argument for it */
3796 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3797 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3798 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003801 }
3802 /* flush useless bits */
3803 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003804 cur_arg += 2;
3805 } else if (!strcmp(args[cur_arg], "header")) {
3806 /* suboption header - needs additional argument for it */
3807 if (*(args[cur_arg+1]) == 0) {
3808 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3809 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003812 }
3813 free(curproxy->fwdfor_hdr_name);
3814 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3815 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3816 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003817 } else if (!strcmp(args[cur_arg], "if-none")) {
3818 curproxy->options &= ~PR_O_FF_ALWAYS;
3819 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003820 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003821 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003822 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003823 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003826 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003827 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003828 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003829 else if (!strcmp(args[1], "originalto")) {
3830 int cur_arg;
3831
3832 /* insert x-original-to field, but not for the IP address listed as an except.
3833 * set default options (ie: bitfield, header name, etc)
3834 */
3835
3836 curproxy->options |= PR_O_ORGTO;
3837
3838 free(curproxy->orgto_hdr_name);
3839 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3840 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3841
Willy Tarreau87cf5142011-08-19 22:57:24 +02003842 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003843 cur_arg = 2;
3844 while (*(args[cur_arg])) {
3845 if (!strcmp(args[cur_arg], "except")) {
3846 /* suboption except - needs additional argument for it */
3847 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3848 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3849 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003852 }
3853 /* flush useless bits */
3854 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3855 cur_arg += 2;
3856 } else if (!strcmp(args[cur_arg], "header")) {
3857 /* suboption header - needs additional argument for it */
3858 if (*(args[cur_arg+1]) == 0) {
3859 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3860 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003863 }
3864 free(curproxy->orgto_hdr_name);
3865 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3866 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3867 cur_arg += 2;
3868 } else {
3869 /* unknown suboption - catchall */
3870 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3871 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003874 }
3875 } /* end while loop */
3876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 else {
3878 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 }
Willy Tarreau93893792009-07-23 13:19:11 +02003882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003884 else if (!strcmp(args[0], "default_backend")) {
3885 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003887
3888 if (*(args[1]) == 0) {
3889 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003892 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003893 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003894 curproxy->defbe.name = strdup(args[1]);
3895 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003899
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003900 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3901 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003903 /* enable reconnections to dispatch */
3904 curproxy->options |= PR_O_REDISP;
3905 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003906 else if (!strcmp(args[0], "http-check")) {
3907 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003908 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003909
3910 if (strcmp(args[1], "disable-on-404") == 0) {
3911 /* enable a graceful server shutdown on an HTTP 404 response */
3912 curproxy->options |= PR_O_DISABLE404;
3913 }
Willy Tarreauef781042010-01-27 11:53:01 +01003914 else if (strcmp(args[1], "send-state") == 0) {
3915 /* enable emission of the apparent state of a server in HTTP checks */
3916 curproxy->options2 |= PR_O2_CHK_SNDST;
3917 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003918 else if (strcmp(args[1], "expect") == 0) {
3919 const char *ptr_arg;
3920 int cur_arg;
3921
3922 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3923 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
3926 }
3927
3928 cur_arg = 2;
3929 /* consider exclamation marks, sole or at the beginning of a word */
3930 while (*(ptr_arg = args[cur_arg])) {
3931 while (*ptr_arg == '!') {
3932 curproxy->options2 ^= PR_O2_EXP_INV;
3933 ptr_arg++;
3934 }
3935 if (*ptr_arg)
3936 break;
3937 cur_arg++;
3938 }
3939 /* now ptr_arg points to the beginning of a word past any possible
3940 * exclamation mark, and cur_arg is the argument which holds this word.
3941 */
3942 if (strcmp(ptr_arg, "status") == 0) {
3943 if (!*(args[cur_arg + 1])) {
3944 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3945 file, linenum, args[0], args[1], ptr_arg);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
3949 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003950 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003951 curproxy->expect_str = strdup(args[cur_arg + 1]);
3952 }
3953 else if (strcmp(ptr_arg, "string") == 0) {
3954 if (!*(args[cur_arg + 1])) {
3955 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3956 file, linenum, args[0], args[1], ptr_arg);
3957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
3959 }
3960 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003961 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003962 curproxy->expect_str = strdup(args[cur_arg + 1]);
3963 }
3964 else if (strcmp(ptr_arg, "rstatus") == 0) {
3965 if (!*(args[cur_arg + 1])) {
3966 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3967 file, linenum, args[0], args[1], ptr_arg);
3968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
3970 }
3971 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003972 free(curproxy->expect_str);
3973 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3974 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003975 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3976 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3977 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3978 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
3982 }
3983 else if (strcmp(ptr_arg, "rstring") == 0) {
3984 if (!*(args[cur_arg + 1])) {
3985 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3986 file, linenum, args[0], args[1], ptr_arg);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
3990 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003991 free(curproxy->expect_str);
3992 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3993 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003994 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3995 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3996 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3997 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
4000 }
4001 }
4002 else {
4003 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4004 file, linenum, args[0], args[1], ptr_arg);
4005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
4007 }
4008 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004009 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004010 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 +02004011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004013 }
4014 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004015 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004016 if (curproxy == &defproxy) {
4017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004020 }
4021
Willy Tarreaub80c2302007-11-30 20:51:32 +01004022 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004023 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004024
4025 if (strcmp(args[1], "fail") == 0) {
4026 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004027 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004028 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4029 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004032 }
4033
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004034 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4035 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4036 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004039 }
4040 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4041 }
4042 else {
4043 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004046 }
4047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048#ifdef TPROXY
4049 else if (!strcmp(args[0], "transparent")) {
4050 /* enable transparent proxy connections */
4051 curproxy->options |= PR_O_TRANSP;
4052 }
4053#endif
4054 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004055 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004056 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004057
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 if (*(args[1]) == 0) {
4059 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062 }
4063 curproxy->maxconn = atol(args[1]);
4064 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004065 else if (!strcmp(args[0], "backlog")) { /* backlog */
4066 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004068
4069 if (*(args[1]) == 0) {
4070 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004073 }
4074 curproxy->backlog = atol(args[1]);
4075 }
Willy Tarreau86034312006-12-29 00:10:33 +01004076 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004077 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004078 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004079
Willy Tarreau86034312006-12-29 00:10:33 +01004080 if (*(args[1]) == 0) {
4081 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004084 }
4085 curproxy->fullconn = atol(args[1]);
4086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004087 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4088 if (*(args[1]) == 0) {
4089 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004093 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4094 if (err) {
4095 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4096 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004099 }
4100 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004101 }
4102 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004103 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004104 if (curproxy == &defproxy) {
4105 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004108 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004109 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004111
Willy Tarreaubaaee002006-06-26 02:48:02 +02004112 if (strchr(args[1], ':') == NULL) {
4113 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004116 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004117 sk = str2sa(args[1]);
4118 if (!sk) {
4119 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
4122 }
4123 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004124 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125 }
4126 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004127 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004128 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004129
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004130 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4131 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004134 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004135 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004136 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4137 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4138 err_code |= ERR_WARN;
4139
4140 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4141 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4142 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4143 }
4144 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4145 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4146 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4147 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004148 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4149 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4150 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4151 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004152 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004153 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
4156 }
4157 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004158 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004160 char *rport, *raddr;
4161 short realport = 0;
4162 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004164 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004169 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004170 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171
4172 if (!*args[2]) {
4173 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004178
4179 err = invalid_char(args[1]);
4180 if (err) {
4181 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4182 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004185 }
4186
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004187 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004188 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004189
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004190 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4191 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4192 err_code |= ERR_ALERT | ERR_ABORT;
4193 goto out;
4194 }
4195
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004196 /* the servers are linked backwards first */
4197 newsrv->next = curproxy->srv;
4198 curproxy->srv = newsrv;
4199 newsrv->proxy = curproxy;
4200 newsrv->conf.file = file;
4201 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202
Simon Hormanaf514952011-06-21 14:34:57 +09004203 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004204 LIST_INIT(&newsrv->pendconns);
4205 do_check = 0;
4206 newsrv->state = SRV_RUNNING; /* early server setup */
4207 newsrv->last_change = now.tv_sec;
4208 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004210 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004211 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004212 * - IP: => port=+0, relative
4213 * - IP:N => port=N, absolute
4214 * - IP:+N => port=+N, relative
4215 * - IP:-N => port=-N, relative
4216 */
4217 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004218 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004219 if (rport) {
4220 *rport++ = 0;
4221 realport = atol(rport);
4222 if (!isdigit((unsigned char)*rport))
4223 newsrv->state |= SRV_MAPPORTS;
4224 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004226
Willy Tarreaufab5a432011-03-04 15:31:53 +01004227 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004228 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004229 if (!sk) {
4230 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
4233 }
4234 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004235 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004236 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004237
4238 if (!sk) {
4239 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4240 file, linenum, newsrv->addr.ss_family, args[2]);
4241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
4243 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004244 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004245
4246 newsrv->check_port = curproxy->defsrv.check_port;
4247 newsrv->inter = curproxy->defsrv.inter;
4248 newsrv->fastinter = curproxy->defsrv.fastinter;
4249 newsrv->downinter = curproxy->defsrv.downinter;
4250 newsrv->rise = curproxy->defsrv.rise;
4251 newsrv->fall = curproxy->defsrv.fall;
4252 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4253 newsrv->minconn = curproxy->defsrv.minconn;
4254 newsrv->maxconn = curproxy->defsrv.maxconn;
4255 newsrv->slowstart = curproxy->defsrv.slowstart;
4256 newsrv->onerror = curproxy->defsrv.onerror;
4257 newsrv->consecutive_errors_limit
4258 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004259#ifdef OPENSSL
4260 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4261#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004262 newsrv->uweight = newsrv->iweight
4263 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004264
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004265 newsrv->curfd = -1; /* no health-check in progress */
4266 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004267
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004268 cur_arg = 3;
4269 } else {
4270 newsrv = &curproxy->defsrv;
4271 cur_arg = 1;
4272 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004273
Willy Tarreaubaaee002006-06-26 02:48:02 +02004274 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004275 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004276 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004277
4278 if (!*args[cur_arg + 1]) {
4279 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4280 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004281 err_code |= ERR_ALERT | ERR_FATAL;
4282 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004283 }
4284
4285 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004286 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004287
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004288 if (newsrv->puid <= 0) {
4289 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004290 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004293 }
4294
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004295 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4296 if (node) {
4297 struct server *target = container_of(node, struct server, conf.id);
4298 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4299 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
4302 }
4303 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004304 cur_arg += 2;
4305 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004306 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004307 newsrv->cookie = strdup(args[cur_arg + 1]);
4308 newsrv->cklen = strlen(args[cur_arg + 1]);
4309 cur_arg += 2;
4310 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004311 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004312 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4313 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4314 cur_arg += 2;
4315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004317 if (!*args[cur_arg + 1]) {
4318 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4319 file, linenum, args[cur_arg]);
4320 err_code |= ERR_ALERT | ERR_FATAL;
4321 goto out;
4322 }
4323
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004325 if (newsrv->rise <= 0) {
4326 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4327 file, linenum, args[cur_arg]);
4328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
4330 }
4331
Willy Tarreau96839092010-03-29 10:02:24 +02004332 if (newsrv->health)
4333 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004334 cur_arg += 2;
4335 }
4336 else if (!strcmp(args[cur_arg], "fall")) {
4337 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004338
4339 if (!*args[cur_arg + 1]) {
4340 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4341 file, linenum, args[cur_arg]);
4342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
4344 }
4345
4346 if (newsrv->fall <= 0) {
4347 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4348 file, linenum, args[cur_arg]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 }
4352
Willy Tarreaubaaee002006-06-26 02:48:02 +02004353 cur_arg += 2;
4354 }
4355 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004356 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4357 if (err) {
4358 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4359 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004362 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004363 if (val <= 0) {
4364 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4365 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004368 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004369 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 cur_arg += 2;
4371 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004372 else if (!strcmp(args[cur_arg], "fastinter")) {
4373 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4374 if (err) {
4375 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4376 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004379 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004380 if (val <= 0) {
4381 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4382 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004385 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004386 newsrv->fastinter = val;
4387 cur_arg += 2;
4388 }
4389 else if (!strcmp(args[cur_arg], "downinter")) {
4390 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4391 if (err) {
4392 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4393 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004396 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004397 if (val <= 0) {
4398 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4399 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004402 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004403 newsrv->downinter = val;
4404 cur_arg += 2;
4405 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004406 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004407 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004408 if (!sk) {
4409 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
4412 }
4413 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004414 cur_arg += 2;
4415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 else if (!strcmp(args[cur_arg], "port")) {
4417 newsrv->check_port = atol(args[cur_arg + 1]);
4418 cur_arg += 2;
4419 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004420 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 newsrv->state |= SRV_BACKUP;
4422 cur_arg ++;
4423 }
Simon Hormanfa461682011-06-25 09:39:49 +09004424 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4425 newsrv->state |= SRV_NON_STICK;
4426 cur_arg ++;
4427 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004428 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4429 newsrv->state |= SRV_SEND_PROXY;
4430 cur_arg ++;
4431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004432 else if (!strcmp(args[cur_arg], "weight")) {
4433 int w;
4434 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004435 if (w < 0 || w > 256) {
4436 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004440 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004441 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 cur_arg += 2;
4443 }
4444 else if (!strcmp(args[cur_arg], "minconn")) {
4445 newsrv->minconn = atol(args[cur_arg + 1]);
4446 cur_arg += 2;
4447 }
4448 else if (!strcmp(args[cur_arg], "maxconn")) {
4449 newsrv->maxconn = atol(args[cur_arg + 1]);
4450 cur_arg += 2;
4451 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004452 else if (!strcmp(args[cur_arg], "maxqueue")) {
4453 newsrv->maxqueue = atol(args[cur_arg + 1]);
4454 cur_arg += 2;
4455 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004456 else if (!strcmp(args[cur_arg], "slowstart")) {
4457 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004458 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004459 if (err) {
4460 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' 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;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004464 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004465 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004466 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 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004471 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004472 cur_arg += 2;
4473 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004474 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004475
4476 if (!*args[cur_arg + 1]) {
4477 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4478 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004481 }
4482
4483 newsrv->trackit = strdup(args[cur_arg + 1]);
4484
4485 cur_arg += 2;
4486 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004487 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 global.maxsock++;
4489 do_check = 1;
4490 cur_arg += 1;
4491 }
Willy Tarreau96839092010-03-29 10:02:24 +02004492 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4493 newsrv->state |= SRV_MAINTAIN;
4494 newsrv->state &= ~SRV_RUNNING;
4495 newsrv->health = 0;
4496 cur_arg += 1;
4497 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004498 else if (!strcmp(args[cur_arg], "ssl")) {
4499#ifdef USE_OPENSSL
4500 newsrv->use_ssl = 1;
4501 cur_arg += 1;
4502#else /* USE_OPENSSL */
4503 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4504 file, linenum, args[cur_arg]);
4505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
4507#endif /* USE_OPENSSL */
4508 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004509 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4510#ifdef USE_OPENSSL
4511 if (!*args[cur_arg + 1]) {
4512 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4513 file, linenum, args[0], args[cur_arg]);
4514 err_code |= ERR_ALERT | ERR_FATAL;
4515 goto out;
4516 }
4517
4518 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4519
4520 cur_arg += 2;
4521 continue;
4522#else
4523 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4524 file, linenum, args[0], args[cur_arg]);
4525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
4527#endif
4528 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004529 else if (!strcmp(args[cur_arg], "nosslv3")) {
4530#ifdef USE_OPENSSL
4531 newsrv->ssl_ctx.nosslv3 = 1;
4532 cur_arg += 1;
4533#else /* USE_OPENSSL */
4534 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4535 file, linenum, args[cur_arg]);
4536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
4538#endif /* USE_OPENSSL */
4539 }
4540 else if (!strcmp(args[cur_arg], "notlsv1")) {
4541#ifdef USE_OPENSSL
4542 newsrv->ssl_ctx.notlsv1 = 1;
4543 cur_arg += 1;
4544#else /* USE_OPENSSL */
4545 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4546 file, linenum, args[cur_arg]);
4547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
4549#endif /* USE_OPENSSL */
4550 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004551 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004552 if (!strcmp(args[cur_arg + 1], "none"))
4553 newsrv->observe = HANA_OBS_NONE;
4554 else if (!strcmp(args[cur_arg + 1], "layer4"))
4555 newsrv->observe = HANA_OBS_LAYER4;
4556 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4557 if (curproxy->mode != PR_MODE_HTTP) {
4558 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4559 file, linenum, args[cur_arg + 1]);
4560 err_code |= ERR_ALERT;
4561 }
4562 newsrv->observe = HANA_OBS_LAYER7;
4563 }
4564 else {
4565 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004566 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004567 file, linenum, args[cur_arg], args[cur_arg + 1]);
4568 err_code |= ERR_ALERT | ERR_FATAL;
4569 goto out;
4570 }
4571
4572 cur_arg += 2;
4573 }
4574 else if (!strcmp(args[cur_arg], "on-error")) {
4575 if (!strcmp(args[cur_arg + 1], "fastinter"))
4576 newsrv->onerror = HANA_ONERR_FASTINTER;
4577 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4578 newsrv->onerror = HANA_ONERR_FAILCHK;
4579 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4580 newsrv->onerror = HANA_ONERR_SUDDTH;
4581 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4582 newsrv->onerror = HANA_ONERR_MARKDWN;
4583 else {
4584 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004585 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004586 file, linenum, args[cur_arg], args[cur_arg + 1]);
4587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
4589 }
4590
4591 cur_arg += 2;
4592 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004593 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4594 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4595 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4596 else {
4597 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4598 file, linenum, args[cur_arg], args[cur_arg + 1]);
4599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
4601 }
4602
4603 cur_arg += 2;
4604 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004605 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4606 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4607 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4608 else {
4609 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4610 file, linenum, args[cur_arg], args[cur_arg + 1]);
4611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
4613 }
4614
4615 cur_arg += 2;
4616 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004617 else if (!strcmp(args[cur_arg], "error-limit")) {
4618 if (!*args[cur_arg + 1]) {
4619 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4620 file, linenum, args[cur_arg]);
4621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
4623 }
4624
4625 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4626
4627 if (newsrv->consecutive_errors_limit <= 0) {
4628 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4629 file, linenum, args[cur_arg]);
4630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
4632 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004633 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004634 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004635 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004636 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004637 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004638
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004640#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004641 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004642 file, linenum, "source", "usesrc");
4643#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004644 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004645 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004646#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649 }
4650 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004651 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4652 if (!sk) {
4653 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
4656 }
4657 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004658
4659 if (port_low != port_high) {
4660 int i;
4661 if (port_low <= 0 || port_low > 65535 ||
4662 port_high <= 0 || port_high > 65535 ||
4663 port_low > port_high) {
4664 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4665 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004668 }
4669 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4670 for (i = 0; i < newsrv->sport_range->size; i++)
4671 newsrv->sport_range->ports[i] = port_low + i;
4672 }
4673
Willy Tarreaubaaee002006-06-26 02:48:02 +02004674 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004675 while (*(args[cur_arg])) {
4676 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004677#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4678#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004679 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4680 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4681 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004682 err_code |= ERR_ALERT | ERR_FATAL;
4683 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004684 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004685#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004686 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004687 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004688 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004691 }
4692 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004693 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004694 newsrv->state |= SRV_TPROXY_CLI;
4695 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004696 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004697 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004698 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4699 char *name, *end;
4700
4701 name = args[cur_arg+1] + 7;
4702 while (isspace(*name))
4703 name++;
4704
4705 end = name;
4706 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4707 end++;
4708
4709 newsrv->state &= ~SRV_TPROXY_MASK;
4710 newsrv->state |= SRV_TPROXY_DYN;
4711 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4712 newsrv->bind_hdr_len = end - name;
4713 memcpy(newsrv->bind_hdr_name, name, end - name);
4714 newsrv->bind_hdr_name[end-name] = '\0';
4715 newsrv->bind_hdr_occ = -1;
4716
4717 /* now look for an occurrence number */
4718 while (isspace(*end))
4719 end++;
4720 if (*end == ',') {
4721 end++;
4722 name = end;
4723 if (*end == '-')
4724 end++;
4725 while (isdigit(*end))
4726 end++;
4727 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4728 }
4729
4730 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4731 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4732 " occurrences values smaller than %d.\n",
4733 file, linenum, MAX_HDR_HISTORY);
4734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
4736 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004737 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004738 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004739 if (!sk) {
4740 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
4743 }
4744 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004745 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004746 }
4747 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004748#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004749 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004750#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004751 cur_arg += 2;
4752 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004753#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004754 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004755 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004756 err_code |= ERR_ALERT | ERR_FATAL;
4757 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004758#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4759 } /* "usesrc" */
4760
4761 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4762#ifdef SO_BINDTODEVICE
4763 if (!*args[cur_arg + 1]) {
4764 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4765 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004766 err_code |= ERR_ALERT | ERR_FATAL;
4767 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004768 }
4769 if (newsrv->iface_name)
4770 free(newsrv->iface_name);
4771
4772 newsrv->iface_name = strdup(args[cur_arg + 1]);
4773 newsrv->iface_len = strlen(newsrv->iface_name);
4774 global.last_checks |= LSTCHK_NETADM;
4775#else
4776 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4777 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004780#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004781 cur_arg += 2;
4782 continue;
4783 }
4784 /* this keyword in not an option of "source" */
4785 break;
4786 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004788 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004789 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4790 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004791 err_code |= ERR_ALERT | ERR_FATAL;
4792 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004795 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004796 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 +01004797 file, linenum, newsrv->id);
4798 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004799 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 +01004800 file, linenum);
4801
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804 }
4805 }
4806
4807 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004808 if (newsrv->trackit) {
4809 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4810 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004813 }
4814
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004815 /* try to get the port from check_addr if check_port not set */
4816 if (!newsrv->check_port)
4817 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004818
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4820 newsrv->check_port = realport; /* by default */
4821 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004822 /* not yet valid, because no port was set on
4823 * the server either. We'll check if we have
4824 * a known port on the first listener.
4825 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004826 struct listener *l = curproxy->listen;
4827 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4828 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004829 }
4830 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4832 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004836
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004837 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004838 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004839 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4840 err_code |= ERR_ALERT | ERR_ABORT;
4841 goto out;
4842 }
4843
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004844 /* Allocate buffer for partial check results... */
4845 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4846 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4847 err_code |= ERR_ALERT | ERR_ABORT;
4848 goto out;
4849 }
4850
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004851 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 newsrv->state |= SRV_CHECKED;
4853 }
4854
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004855 if (!defsrv) {
4856 if (newsrv->state & SRV_BACKUP)
4857 curproxy->srv_bck++;
4858 else
4859 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004860
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004861 newsrv->prev_state = newsrv->state;
4862 }
William Lallemanda73203e2012-03-12 12:48:57 +01004863 }
4864
4865 else if (strcmp(args[0], "unique-id-format") == 0) {
4866 if (!*(args[1])) {
4867 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
4870 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004871 free(curproxy->uniqueid_format_string);
4872 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004873 }
William Lallemanda73203e2012-03-12 12:48:57 +01004874
4875 else if (strcmp(args[0], "unique-id-header") == 0) {
4876 if (!*(args[1])) {
4877 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
4880 }
4881 free(curproxy->header_unique_id);
4882 curproxy->header_unique_id = strdup(args[1]);
4883 }
4884
William Lallemand723b73a2012-02-08 16:37:49 +01004885 else if (strcmp(args[0], "log-format") == 0) {
4886 if (!*(args[1])) {
4887 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
4890 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004891
4892 if (curproxy->logformat_string != default_http_log_format &&
4893 curproxy->logformat_string != default_tcp_log_format &&
4894 curproxy->logformat_string != clf_http_log_format)
4895 free(curproxy->logformat_string);
4896 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 }
William Lallemand723b73a2012-02-08 16:37:49 +01004898
William Lallemand0f99e342011-10-12 17:50:54 +02004899 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4900 /* delete previous herited or defined syslog servers */
4901 struct logsrv *back;
4902
4903 if (*(args[1]) != 0) {
4904 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
4907 }
4908
William Lallemand723b73a2012-02-08 16:37:49 +01004909 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4910 LIST_DEL(&tmplogsrv->list);
4911 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004912 }
4913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004915 struct logsrv *logsrv;
4916
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004918 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004919 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004920 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004921 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004922 LIST_INIT(&node->list);
4923 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 }
4926 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004927
4928 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929
William Lallemand0f99e342011-10-12 17:50:54 +02004930 logsrv->facility = get_log_facility(args[2]);
4931 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
4935
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 }
4937
William Lallemand0f99e342011-10-12 17:50:54 +02004938 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004940 logsrv->level = get_log_level(args[3]);
4941 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
4945
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 }
4947 }
4948
William Lallemand0f99e342011-10-12 17:50:54 +02004949 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004950 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004951 logsrv->minlvl = get_log_level(args[4]);
4952 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004953 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004954 err_code |= ERR_ALERT | ERR_FATAL;
4955 goto out;
4956
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004957 }
4958 }
4959
Robert Tsai81ae1952007-12-05 10:47:29 +01004960 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004961 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004962 if (!sk) {
4963 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004964 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
4967 }
William Lallemand0f99e342011-10-12 17:50:54 +02004968 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004969 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004970 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004971 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004972 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
4975 }
William Lallemand0f99e342011-10-12 17:50:54 +02004976 logsrv->addr = *sk;
4977 if (!get_host_port(&logsrv->addr))
4978 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
William Lallemand0f99e342011-10-12 17:50:54 +02004980
4981 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 }
4983 else {
4984 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4985 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
4989 }
4990 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004991 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004992 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004993
Willy Tarreau977b8e42006-12-29 14:19:17 +01004994 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004995 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004996
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004998 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4999 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005000 err_code |= ERR_ALERT | ERR_FATAL;
5001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005003
5004 /* we must first clear any optional default setting */
5005 curproxy->options &= ~PR_O_TPXY_MASK;
5006 free(curproxy->iface_name);
5007 curproxy->iface_name = NULL;
5008 curproxy->iface_len = 0;
5009
Willy Tarreaud5191e72010-02-09 20:50:45 +01005010 sk = str2sa(args[1]);
5011 if (!sk) {
5012 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5013 err_code |= ERR_ALERT | ERR_FATAL;
5014 goto out;
5015 }
5016 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005018
5019 cur_arg = 2;
5020 while (*(args[cur_arg])) {
5021 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005022#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
5023#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005024 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
5025 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5026 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005029 }
5030#endif
5031 if (!*args[cur_arg + 1]) {
5032 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5033 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005034 err_code |= ERR_ALERT | ERR_FATAL;
5035 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005036 }
5037
5038 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005039 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005040 curproxy->options |= PR_O_TPXY_CLI;
5041 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005042 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005043 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005044 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5045 char *name, *end;
5046
5047 name = args[cur_arg+1] + 7;
5048 while (isspace(*name))
5049 name++;
5050
5051 end = name;
5052 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5053 end++;
5054
5055 curproxy->options &= ~PR_O_TPXY_MASK;
5056 curproxy->options |= PR_O_TPXY_DYN;
5057 curproxy->bind_hdr_name = calloc(1, end - name + 1);
5058 curproxy->bind_hdr_len = end - name;
5059 memcpy(curproxy->bind_hdr_name, name, end - name);
5060 curproxy->bind_hdr_name[end-name] = '\0';
5061 curproxy->bind_hdr_occ = -1;
5062
5063 /* now look for an occurrence number */
5064 while (isspace(*end))
5065 end++;
5066 if (*end == ',') {
5067 end++;
5068 name = end;
5069 if (*end == '-')
5070 end++;
5071 while (isdigit(*end))
5072 end++;
5073 curproxy->bind_hdr_occ = strl2ic(name, end-name);
5074 }
5075
5076 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
5077 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5078 " occurrences values smaller than %d.\n",
5079 file, linenum, MAX_HDR_HISTORY);
5080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
5082 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005083 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005084 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005085 if (!sk) {
5086 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
5089 }
5090 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005091 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005092 }
5093 global.last_checks |= LSTCHK_NETADM;
5094#if !defined(CONFIG_HAP_LINUX_TPROXY)
5095 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005096#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005097#else /* no TPROXY support */
5098 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005099 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005102#endif
5103 cur_arg += 2;
5104 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005105 }
5106
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005107 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5108#ifdef SO_BINDTODEVICE
5109 if (!*args[cur_arg + 1]) {
5110 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5111 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005114 }
5115 if (curproxy->iface_name)
5116 free(curproxy->iface_name);
5117
5118 curproxy->iface_name = strdup(args[cur_arg + 1]);
5119 curproxy->iface_len = strlen(curproxy->iface_name);
5120 global.last_checks |= LSTCHK_NETADM;
5121#else
5122 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5123 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005126#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005127 cur_arg += 2;
5128 continue;
5129 }
5130 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
5131 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005134 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005136 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5137 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5138 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005141 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005143 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005144 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5145 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005148 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005149
5150 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005151 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005152 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005153 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005155 }
5156 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005157 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005158 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005159 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005160 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005162 }
5163 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005164 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005165 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005166 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005167 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005169 }
5170 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005171 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005172 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005173 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005174 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 }
5177 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005179 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005180 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005181 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005184 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005186 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005187 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005188 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005189 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005190 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005191 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005193 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005194 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005195 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005196 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005197 }
5198 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005200 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005201 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005202 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005203 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005204 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005206 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005207 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5208 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005209 err_code |= ERR_ALERT | ERR_FATAL;
5210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005211 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005212
5213 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005214 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005215 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005216 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218 }
5219 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005220 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005221 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005222 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005223 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 }
5226 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005227 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005228 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005229 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005230 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 }
5233 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005234 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005235 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005236 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005237 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005239 }
5240 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005241 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005242 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005243 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005244 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005246 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005247 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005248 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005249 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005250 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005251 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005252 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005255 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005256
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 if (curproxy == &defproxy) {
5258 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005262 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 if (*(args[1]) == 0) {
5266 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005267 err_code |= ERR_ALERT | ERR_FATAL;
5268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005270
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005271 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005272 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5273 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5274 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005275 err_code |= ERR_ALERT | ERR_FATAL;
5276 goto out;
5277 }
5278 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5279 }
5280 else if (*args[2]) {
5281 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5282 file, linenum, args[0], args[2]);
5283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
5285 }
5286
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005287 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005288 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005289 wl->s = strdup(args[1]);
5290 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005291 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 }
5293 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5296 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005300
Willy Tarreauade5ec42010-01-28 19:33:49 +01005301 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005302 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005303 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005304 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 }
5307 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005308 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005309 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005310 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005311 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 }
5314 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005315 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005316 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005317 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005318 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 }
5321 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005322 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5324 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005325 err_code |= ERR_ALERT | ERR_FATAL;
5326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327 }
5328
Willy Tarreauade5ec42010-01-28 19:33:49 +01005329 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005330 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005331 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005332 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 }
5335 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005336 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005337 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005338 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005339 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 }
5342 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005343 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005344 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005345 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005346 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 }
5349 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005350 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005351
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 if (curproxy == &defproxy) {
5353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005357 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005358 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 if (*(args[1]) == 0) {
5361 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005362 err_code |= ERR_ALERT | ERR_FATAL;
5363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 }
5365
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005366 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005367 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5368 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5369 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
5372 }
5373 err_code |= warnif_cond_requires_req(cond, file, linenum);
5374 }
5375 else if (*args[2]) {
5376 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5377 file, linenum, args[0], args[2]);
5378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
5380 }
5381
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005382 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005383 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005384 wl->s = strdup(args[1]);
5385 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 }
5387 else if (!strcmp(args[0], "errorloc") ||
5388 !strcmp(args[0], "errorloc302") ||
5389 !strcmp(args[0], "errorloc303")) { /* error location */
5390 int errnum, errlen;
5391 char *err;
5392
Willy Tarreau977b8e42006-12-29 14:19:17 +01005393 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005394 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005395
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005397 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 }
5401
5402 errnum = atol(args[1]);
5403 if (!strcmp(args[0], "errorloc303")) {
5404 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5405 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5406 } else {
5407 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5408 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5409 }
5410
Willy Tarreau0f772532006-12-23 20:51:41 +01005411 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5412 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005413 chunk_destroy(&curproxy->errmsg[rc]);
5414 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005415 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005417 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005418
5419 if (rc >= HTTP_ERR_SIZE) {
5420 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5421 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 free(err);
5423 }
5424 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005425 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5426 int errnum, errlen, fd;
5427 char *err;
5428 struct stat stat;
5429
5430 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005431 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005432
5433 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005434 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005435 err_code |= ERR_ALERT | ERR_FATAL;
5436 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005437 }
5438
5439 fd = open(args[2], O_RDONLY);
5440 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5441 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5442 file, linenum, args[2], args[1]);
5443 if (fd >= 0)
5444 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005447 }
5448
Willy Tarreau27a674e2009-08-17 07:23:33 +02005449 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005450 errlen = stat.st_size;
5451 } else {
5452 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005453 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005454 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005455 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005456 }
5457
5458 err = malloc(errlen); /* malloc() must succeed during parsing */
5459 errnum = read(fd, err, errlen);
5460 if (errnum != errlen) {
5461 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5462 file, linenum, args[2], args[1]);
5463 close(fd);
5464 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005467 }
5468 close(fd);
5469
5470 errnum = atol(args[1]);
5471 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5472 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005473 chunk_destroy(&curproxy->errmsg[rc]);
5474 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005475 break;
5476 }
5477 }
5478
5479 if (rc >= HTTP_ERR_SIZE) {
5480 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5481 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005482 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005483 free(err);
5484 }
5485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005487 struct cfg_kw_list *kwl;
5488 int index;
5489
5490 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5491 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5492 if (kwl->kw[index].section != CFG_LISTEN)
5493 continue;
5494 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5495 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005496 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005497 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005498 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005499 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005500 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005501 err_code |= ERR_ALERT | ERR_FATAL;
5502 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005503 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005504 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005505 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005506 err_code |= ERR_WARN;
5507 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005508 }
Willy Tarreau93893792009-07-23 13:19:11 +02005509 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005510 }
5511 }
5512 }
5513
Willy Tarreau6daf3432008-01-22 16:44:08 +01005514 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005515 err_code |= ERR_ALERT | ERR_FATAL;
5516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 }
Willy Tarreau93893792009-07-23 13:19:11 +02005518 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005519 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005520 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521}
5522
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005523int
5524cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5525{
5526
5527 int err_code = 0;
5528 const char *err;
5529
5530 if (!strcmp(args[0], "userlist")) { /* new userlist */
5531 struct userlist *newul;
5532
5533 if (!*args[1]) {
5534 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5535 file, linenum, args[0]);
5536 err_code |= ERR_ALERT | ERR_FATAL;
5537 goto out;
5538 }
5539
5540 err = invalid_char(args[1]);
5541 if (err) {
5542 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5543 file, linenum, *err, args[0], args[1]);
5544 err_code |= ERR_ALERT | ERR_FATAL;
5545 goto out;
5546 }
5547
5548 for (newul = userlist; newul; newul = newul->next)
5549 if (!strcmp(newul->name, args[1])) {
5550 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5551 file, linenum, args[1]);
5552 err_code |= ERR_WARN;
5553 goto out;
5554 }
5555
5556 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5557 if (!newul) {
5558 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5559 err_code |= ERR_ALERT | ERR_ABORT;
5560 goto out;
5561 }
5562
5563 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5564 newul->name = strdup(args[1]);
5565
5566 if (!newul->groupusers | !newul->name) {
5567 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5568 err_code |= ERR_ALERT | ERR_ABORT;
5569 goto out;
5570 }
5571
5572 newul->next = userlist;
5573 userlist = newul;
5574
5575 } else if (!strcmp(args[0], "group")) { /* new group */
5576 int cur_arg, i;
5577 const char *err;
5578
5579 if (!*args[1]) {
5580 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5581 file, linenum, args[0]);
5582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
5584 }
5585
5586 err = invalid_char(args[1]);
5587 if (err) {
5588 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5589 file, linenum, *err, args[0], args[1]);
5590 err_code |= ERR_ALERT | ERR_FATAL;
5591 goto out;
5592 }
5593
5594 for(i = 0; i < userlist->grpcnt; i++)
5595 if (!strcmp(userlist->groups[i], args[1])) {
5596 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5597 file, linenum, args[1], userlist->name);
5598 err_code |= ERR_ALERT;
5599 goto out;
5600 }
5601
5602 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5603 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5604 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
5607 }
5608
5609 cur_arg = 2;
5610
5611 while (*args[cur_arg]) {
5612 if (!strcmp(args[cur_arg], "users")) {
5613 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5614 cur_arg += 2;
5615 continue;
5616 } else {
5617 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5618 file, linenum, args[0]);
5619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
5621 }
5622 }
5623
5624 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5625 } else if (!strcmp(args[0], "user")) { /* new user */
5626 struct auth_users *newuser;
5627 int cur_arg;
5628
5629 if (!*args[1]) {
5630 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5631 file, linenum, args[0]);
5632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
5634 }
5635
5636 for (newuser = userlist->users; newuser; newuser = newuser->next)
5637 if (!strcmp(newuser->user, args[1])) {
5638 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5639 file, linenum, args[1], userlist->name);
5640 err_code |= ERR_ALERT;
5641 goto out;
5642 }
5643
5644 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5645 if (!newuser) {
5646 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5647 err_code |= ERR_ALERT | ERR_ABORT;
5648 goto out;
5649 }
5650
5651 newuser->user = strdup(args[1]);
5652
5653 newuser->next = userlist->users;
5654 userlist->users = newuser;
5655
5656 cur_arg = 2;
5657
5658 while (*args[cur_arg]) {
5659 if (!strcmp(args[cur_arg], "password")) {
5660#ifndef CONFIG_HAP_CRYPT
5661 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5662 file, linenum);
5663 err_code |= ERR_ALERT;
5664#endif
5665 newuser->pass = strdup(args[cur_arg + 1]);
5666 cur_arg += 2;
5667 continue;
5668 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5669 newuser->pass = strdup(args[cur_arg + 1]);
5670 newuser->flags |= AU_O_INSECURE;
5671 cur_arg += 2;
5672 continue;
5673 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005674 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005675 cur_arg += 2;
5676 continue;
5677 } else {
5678 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5679 file, linenum, args[0]);
5680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
5682 }
5683 }
5684 } else {
5685 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5686 err_code |= ERR_ALERT | ERR_FATAL;
5687 }
5688
5689out:
5690 return err_code;
5691}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005692
5693/*
5694 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005695 * Returns the error code, 0 if OK, or any combination of :
5696 * - ERR_ABORT: must abort ASAP
5697 * - ERR_FATAL: we can continue parsing but not start the service
5698 * - ERR_WARN: a warning has been emitted
5699 * - ERR_ALERT: an alert has been emitted
5700 * Only the two first ones can stop processing, the two others are just
5701 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005703int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005704{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005705 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706 FILE *f;
5707 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005708 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005709 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 if ((f=fopen(file,"r")) == NULL)
5712 return -1;
5713
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005714 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005715 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005716 char *end;
5717 char *args[MAX_LINE_ARGS + 1];
5718 char *line = thisline;
5719
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 linenum++;
5721
5722 end = line + strlen(line);
5723
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005724 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5725 /* Check if we reached the limit and the last char is not \n.
5726 * Watch out for the last line without the terminating '\n'!
5727 */
5728 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005729 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005730 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005731 }
5732
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005734 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005735 line++;
5736
5737 arg = 0;
5738 args[arg] = line;
5739
5740 while (*line && arg < MAX_LINE_ARGS) {
5741 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5742 * C equivalent value. Other combinations left unchanged (eg: \1).
5743 */
5744 if (*line == '\\') {
5745 int skip = 0;
5746 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5747 *line = line[1];
5748 skip = 1;
5749 }
5750 else if (line[1] == 'r') {
5751 *line = '\r';
5752 skip = 1;
5753 }
5754 else if (line[1] == 'n') {
5755 *line = '\n';
5756 skip = 1;
5757 }
5758 else if (line[1] == 't') {
5759 *line = '\t';
5760 skip = 1;
5761 }
5762 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005763 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 unsigned char hex1, hex2;
5765 hex1 = toupper(line[2]) - '0';
5766 hex2 = toupper(line[3]) - '0';
5767 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5768 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5769 *line = (hex1<<4) + hex2;
5770 skip = 3;
5771 }
5772 else {
5773 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005774 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 }
5776 }
5777 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005778 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005779 end -= skip;
5780 }
5781 line++;
5782 }
5783 else if (*line == '#' || *line == '\n' || *line == '\r') {
5784 /* end of string, end of loop */
5785 *line = 0;
5786 break;
5787 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005788 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005790 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005791 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 line++;
5793 args[++arg] = line;
5794 }
5795 else {
5796 line++;
5797 }
5798 }
5799
5800 /* empty line */
5801 if (!**args)
5802 continue;
5803
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005804 if (*line) {
5805 /* we had to stop due to too many args.
5806 * Let's terminate the string, print the offending part then cut the
5807 * last arg.
5808 */
5809 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5810 line++;
5811 *line = '\0';
5812
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005813 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005814 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005815 err_code |= ERR_ALERT | ERR_FATAL;
5816 args[arg] = line;
5817 }
5818
Willy Tarreau540abe42007-05-02 20:50:16 +02005819 /* zero out remaining args and ensure that at least one entry
5820 * is zeroed out.
5821 */
5822 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005823 args[arg] = line;
5824 }
5825
Willy Tarreau3842f002009-06-14 11:39:52 +02005826 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005827 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005828 char *tmp;
5829
Willy Tarreau3842f002009-06-14 11:39:52 +02005830 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005831 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005832 for (arg=0; *args[arg+1]; arg++)
5833 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005834 *tmp = '\0'; // fix the next arg to \0
5835 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005836 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005837 else if (!strcmp(args[0], "default")) {
5838 kwm = KWM_DEF;
5839 for (arg=0; *args[arg+1]; arg++)
5840 args[arg] = args[arg+1]; // shift args after inversion
5841 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005842
William Lallemand0f99e342011-10-12 17:50:54 +02005843 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5844 strcmp(args[0], "log") != 0) {
5845 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005846 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005847 }
5848
Willy Tarreau977b8e42006-12-29 14:19:17 +01005849 if (!strcmp(args[0], "listen") ||
5850 !strcmp(args[0], "frontend") ||
5851 !strcmp(args[0], "backend") ||
5852 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005853 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005854 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005855 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005856 cursection = strdup(args[0]);
5857 }
5858 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005860 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005861 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005862 }
5863 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005864 confsect = CFG_USERLIST;
5865 free(cursection);
5866 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005867 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005868 else if (!strcmp(args[0], "peers")) {
5869 confsect = CFG_PEERS;
5870 free(cursection);
5871 cursection = strdup(args[0]);
5872 }
5873
Willy Tarreaubaaee002006-06-26 02:48:02 +02005874 /* else it's a section keyword */
5875
5876 switch (confsect) {
5877 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005878 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005879 break;
5880 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005881 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005882 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005883 case CFG_USERLIST:
5884 err_code |= cfg_parse_users(file, linenum, args, kwm);
5885 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005886 case CFG_PEERS:
5887 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5888 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005890 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005891 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005893
5894 if (err_code & ERR_ABORT)
5895 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005896 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005897 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005898 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005899 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005900 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005901}
5902
Willy Tarreaubb925012009-07-23 13:36:36 +02005903/*
5904 * Returns the error code, 0 if OK, or any combination of :
5905 * - ERR_ABORT: must abort ASAP
5906 * - ERR_FATAL: we can continue parsing but not start the service
5907 * - ERR_WARN: a warning has been emitted
5908 * - ERR_ALERT: an alert has been emitted
5909 * Only the two first ones can stop processing, the two others are just
5910 * indicators.
5911 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005912int check_config_validity()
5913{
5914 int cfgerr = 0;
5915 struct proxy *curproxy = NULL;
5916 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005917 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005918 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005919 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005920 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005921
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005922 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005923 /*
5924 * Now, check for the integrity of all that we have collected.
5925 */
5926
5927 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005928 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005929
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005930 /* first, we will invert the proxy list order */
5931 curproxy = NULL;
5932 while (proxy) {
5933 struct proxy *next;
5934
5935 next = proxy->next;
5936 proxy->next = curproxy;
5937 curproxy = proxy;
5938 if (!next)
5939 break;
5940 proxy = next;
5941 }
5942
Willy Tarreaubaaee002006-06-26 02:48:02 +02005943 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005944 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005945 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005946 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005947 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005948 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005949 unsigned int next_id;
5950
5951 if (!curproxy->uuid) {
5952 /* proxy ID not set, use automatic numbering with first
5953 * spare entry starting with next_pxid.
5954 */
5955 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5956 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5957 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005958 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005959 next_pxid++;
5960
Willy Tarreau55ea7572007-06-17 19:56:27 +02005961
Willy Tarreaubaaee002006-06-26 02:48:02 +02005962 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005963 /* ensure we don't keep listeners uselessly bound */
5964 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005965 curproxy = curproxy->next;
5966 continue;
5967 }
5968
Willy Tarreauff01a212009-03-15 13:46:16 +01005969 switch (curproxy->mode) {
5970 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005971 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005972 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005973 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5974 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005975 cfgerr++;
5976 }
5977
5978 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005979 Warning("config : servers will be ignored for %s '%s'.\n",
5980 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005981 break;
5982
5983 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005984 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005985 break;
5986
5987 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005988 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005989 break;
5990 }
5991
5992 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005993 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5994 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995 cfgerr++;
5996 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005997
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005998 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005999 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006000 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006001 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6002 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006003 cfgerr++;
6004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006005#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006006 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006007 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6008 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006009 cfgerr++;
6010 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006011#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006012 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006013 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6014 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006015 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006016 }
6017 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006018 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006019 /* If no LB algo is set in a backend, and we're not in
6020 * transparent mode, dispatch mode nor proxy mode, we
6021 * want to use balance roundrobin by default.
6022 */
6023 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6024 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006025 }
6026 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006027
Willy Tarreau1620ec32011-08-06 17:05:02 +02006028 if (curproxy->options & PR_O_DISPATCH)
6029 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6030 else if (curproxy->options & PR_O_HTTP_PROXY)
6031 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6032 else if (curproxy->options & PR_O_TRANSP)
6033 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006034
Willy Tarreau1620ec32011-08-06 17:05:02 +02006035 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6036 if (curproxy->options & PR_O_DISABLE404) {
6037 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6038 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6039 err_code |= ERR_WARN;
6040 curproxy->options &= ~PR_O_DISABLE404;
6041 }
6042 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6043 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6044 "send-state", proxy_type_str(curproxy), curproxy->id);
6045 err_code |= ERR_WARN;
6046 curproxy->options &= ~PR_O2_CHK_SNDST;
6047 }
Willy Tarreauef781042010-01-27 11:53:01 +01006048 }
6049
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006050 /* if a default backend was specified, let's find it */
6051 if (curproxy->defbe.name) {
6052 struct proxy *target;
6053
Alex Williams96532db2009-11-01 21:27:13 -05006054 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006055 if (!target) {
6056 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6057 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006058 cfgerr++;
6059 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006060 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6061 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006062 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006063 } else {
6064 free(curproxy->defbe.name);
6065 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006066 /* we force the backend to be present on at least all of
6067 * the frontend's processes.
6068 */
6069 target->bind_proc = curproxy->bind_proc ?
6070 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006071
6072 /* Emit a warning if this proxy also has some servers */
6073 if (curproxy->srv) {
6074 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6075 curproxy->id);
6076 err_code |= ERR_WARN;
6077 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006078 }
6079 }
6080
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006081 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006082 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6083 /* map jump target for ACT_SETBE in req_rep chain */
6084 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006085 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006086 struct proxy *target;
6087
Willy Tarreaua496b602006-12-17 23:15:24 +01006088 if (exp->action != ACT_SETBE)
6089 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006090
Alex Williams96532db2009-11-01 21:27:13 -05006091 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006092 if (!target) {
6093 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6094 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006095 cfgerr++;
6096 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006097 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6098 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006099 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006100 } else {
6101 free((void *)exp->replace);
6102 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006103 /* we force the backend to be present on at least all of
6104 * the frontend's processes.
6105 */
6106 target->bind_proc = curproxy->bind_proc ?
6107 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006108 }
6109 }
6110 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006111
6112 /* find the target proxy for 'use_backend' rules */
6113 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006114 struct proxy *target;
6115
Alex Williams96532db2009-11-01 21:27:13 -05006116 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006117
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006118 if (!target) {
6119 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6120 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006121 cfgerr++;
6122 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006123 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6124 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006125 cfgerr++;
6126 } else {
6127 free((void *)rule->be.name);
6128 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006129 /* we force the backend to be present on at least all of
6130 * the frontend's processes.
6131 */
6132 target->bind_proc = curproxy->bind_proc ?
6133 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006134 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006135 }
6136
6137 /* find the target proxy for 'use_backend' rules */
6138 list_for_each_entry(srule, &curproxy->server_rules, list) {
6139 struct server *target = findserver(curproxy, srule->srv.name);
6140
6141 if (!target) {
6142 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6143 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6144 cfgerr++;
6145 continue;
6146 }
6147 free((void *)srule->srv.name);
6148 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006149 }
6150
Emeric Brunb982a3d2010-01-04 15:45:53 +01006151 /* find the target table for 'stick' rules */
6152 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6153 struct proxy *target;
6154
Emeric Brun1d33b292010-01-04 15:47:17 +01006155 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6156 if (mrule->flags & STK_IS_STORE)
6157 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6158
Emeric Brunb982a3d2010-01-04 15:45:53 +01006159 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006160 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006161 else
6162 target = curproxy;
6163
6164 if (!target) {
6165 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6166 curproxy->id, mrule->table.name);
6167 cfgerr++;
6168 }
6169 else if (target->table.size == 0) {
6170 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6171 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6172 cfgerr++;
6173 }
Willy Tarreau12785782012-04-27 21:37:17 +02006174 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6175 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006176 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6177 cfgerr++;
6178 }
6179 else {
6180 free((void *)mrule->table.name);
6181 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006182 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006183 }
6184 }
6185
6186 /* find the target table for 'store response' rules */
6187 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6188 struct proxy *target;
6189
Emeric Brun1d33b292010-01-04 15:47:17 +01006190 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6191
Emeric Brunb982a3d2010-01-04 15:45:53 +01006192 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006193 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006194 else
6195 target = curproxy;
6196
6197 if (!target) {
6198 Alert("Proxy '%s': unable to find store table '%s'.\n",
6199 curproxy->id, mrule->table.name);
6200 cfgerr++;
6201 }
6202 else if (target->table.size == 0) {
6203 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6204 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6205 cfgerr++;
6206 }
Willy Tarreau12785782012-04-27 21:37:17 +02006207 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6208 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006209 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6210 cfgerr++;
6211 }
6212 else {
6213 free((void *)mrule->table.name);
6214 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006215 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006216 }
6217 }
6218
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006219 /* find the target table for 'tcp-request' layer 4 rules */
6220 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6221 struct proxy *target;
6222
Willy Tarreau56123282010-08-06 19:06:56 +02006223 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006224 continue;
6225
6226 if (trule->act_prm.trk_ctr.table.n)
6227 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6228 else
6229 target = curproxy;
6230
6231 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006232 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6233 curproxy->id, trule->act_prm.trk_ctr.table.n,
6234 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006235 cfgerr++;
6236 }
6237 else if (target->table.size == 0) {
6238 Alert("Proxy '%s': table '%s' used but not configured.\n",
6239 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6240 cfgerr++;
6241 }
6242 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006243 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 +02006244 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6245 cfgerr++;
6246 }
6247 else {
6248 free(trule->act_prm.trk_ctr.table.n);
6249 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006250 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006251 * to pass a list of counters to track and allocate them right here using
6252 * stktable_alloc_data_type().
6253 */
6254 }
6255 }
6256
Willy Tarreaud1f96522010-08-03 19:34:32 +02006257 /* find the target table for 'tcp-request' layer 6 rules */
6258 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6259 struct proxy *target;
6260
Willy Tarreau56123282010-08-06 19:06:56 +02006261 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006262 continue;
6263
6264 if (trule->act_prm.trk_ctr.table.n)
6265 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6266 else
6267 target = curproxy;
6268
6269 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006270 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6271 curproxy->id, trule->act_prm.trk_ctr.table.n,
6272 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006273 cfgerr++;
6274 }
6275 else if (target->table.size == 0) {
6276 Alert("Proxy '%s': table '%s' used but not configured.\n",
6277 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6278 cfgerr++;
6279 }
6280 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006281 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 +02006282 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6283 cfgerr++;
6284 }
6285 else {
6286 free(trule->act_prm.trk_ctr.table.n);
6287 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006288 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006289 * to pass a list of counters to track and allocate them right here using
6290 * stktable_alloc_data_type().
6291 */
6292 }
6293 }
6294
Emeric Brun32da3c42010-09-23 18:39:19 +02006295 if (curproxy->table.peers.name) {
6296 struct peers *curpeers = peers;
6297
6298 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6299 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6300 free((void *)curproxy->table.peers.name);
6301 curproxy->table.peers.p = peers;
6302 break;
6303 }
6304 }
6305
6306 if (!curpeers) {
6307 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6308 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006309 free((void *)curproxy->table.peers.name);
6310 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006311 cfgerr++;
6312 }
6313 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006314 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6315 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006316 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006317 cfgerr++;
6318 }
6319 }
6320
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006321 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006322 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006323 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6324 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6325 "proxy", curproxy->id);
6326 cfgerr++;
6327 goto out_uri_auth_compat;
6328 }
6329
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006330 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006331 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006332 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006333 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006334
Willy Tarreau95fa4692010-02-01 13:05:50 +01006335 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6336 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006337
6338 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006339 uri_auth_compat_req[i++] = "realm";
6340 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6341 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006342
Willy Tarreau95fa4692010-02-01 13:05:50 +01006343 uri_auth_compat_req[i++] = "unless";
6344 uri_auth_compat_req[i++] = "{";
6345 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6346 uri_auth_compat_req[i++] = "}";
6347 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006348
Willy Tarreauff011f22011-01-06 17:51:27 +01006349 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6350 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006351 cfgerr++;
6352 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006353 }
6354
Willy Tarreauff011f22011-01-06 17:51:27 +01006355 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006356
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006357 if (curproxy->uri_auth->auth_realm) {
6358 free(curproxy->uri_auth->auth_realm);
6359 curproxy->uri_auth->auth_realm = NULL;
6360 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006361
6362 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006363 }
6364out_uri_auth_compat:
6365
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006366 cfgerr += acl_find_targets(curproxy);
6367
Willy Tarreau2738a142006-07-08 17:28:09 +02006368 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006369 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006370 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006371 (!curproxy->timeout.connect ||
6372 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006373 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006374 " | While not properly invalid, you will certainly encounter various problems\n"
6375 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006376 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006377 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006378 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006379 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006380
Willy Tarreau1fa31262007-12-03 00:36:16 +01006381 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6382 * We must still support older configurations, so let's find out whether those
6383 * parameters have been set or must be copied from contimeouts.
6384 */
6385 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006386 if (!curproxy->timeout.tarpit ||
6387 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006388 /* tarpit timeout not set. We search in the following order:
6389 * default.tarpit, curr.connect, default.connect.
6390 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006391 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006392 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006393 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006394 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006395 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006396 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006397 }
6398 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006399 (!curproxy->timeout.queue ||
6400 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006401 /* queue timeout not set. We search in the following order:
6402 * default.queue, curr.connect, default.connect.
6403 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006404 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006405 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006406 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006407 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006408 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006409 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006410 }
6411 }
6412
Willy Tarreau1620ec32011-08-06 17:05:02 +02006413 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006414 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6415 curproxy->check_req = (char *)malloc(curproxy->check_len);
6416 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006417 }
6418
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006419 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006420 if (curproxy->nb_req_cap) {
6421 if (curproxy->mode == PR_MODE_HTTP) {
6422 curproxy->req_cap_pool = create_pool("ptrcap",
6423 curproxy->nb_req_cap * sizeof(char *),
6424 MEM_F_SHARED);
6425 } else {
6426 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6427 proxy_type_str(curproxy), curproxy->id);
6428 err_code |= ERR_WARN;
6429 curproxy->to_log &= ~LW_REQHDR;
6430 curproxy->nb_req_cap = 0;
6431 }
6432 }
6433
6434 if (curproxy->nb_rsp_cap) {
6435 if (curproxy->mode == PR_MODE_HTTP) {
6436 curproxy->rsp_cap_pool = create_pool("ptrcap",
6437 curproxy->nb_rsp_cap * sizeof(char *),
6438 MEM_F_SHARED);
6439 } else {
6440 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6441 proxy_type_str(curproxy), curproxy->id);
6442 err_code |= ERR_WARN;
6443 curproxy->to_log &= ~LW_REQHDR;
6444 curproxy->nb_rsp_cap = 0;
6445 }
6446 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006447
Willy Tarreau196729e2012-05-31 19:30:26 +02006448 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006449 if (!(curproxy->cap & PR_CAP_FE)) {
6450 if (curproxy->logformat_string != default_http_log_format &&
6451 curproxy->logformat_string != default_tcp_log_format &&
6452 curproxy->logformat_string != clf_http_log_format)
6453 free(curproxy->logformat_string);
6454 curproxy->logformat_string = NULL;
6455 }
6456
Willy Tarreau196729e2012-05-31 19:30:26 +02006457 if (curproxy->logformat_string)
6458 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6459
6460 if (curproxy->uniqueid_format_string)
6461 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6462
Willy Tarreaubaaee002006-06-26 02:48:02 +02006463 /* first, we will invert the servers list order */
6464 newsrv = NULL;
6465 while (curproxy->srv) {
6466 struct server *next;
6467
6468 next = curproxy->srv->next;
6469 curproxy->srv->next = newsrv;
6470 newsrv = curproxy->srv;
6471 if (!next)
6472 break;
6473 curproxy->srv = next;
6474 }
6475
Willy Tarreaudd701652010-05-25 23:03:02 +02006476 /* assign automatic UIDs to servers which don't have one yet */
6477 next_id = 1;
6478 newsrv = curproxy->srv;
6479 while (newsrv != NULL) {
6480 if (!newsrv->puid) {
6481 /* server ID not set, use automatic numbering with first
6482 * spare entry starting with next_svid.
6483 */
6484 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6485 newsrv->conf.id.key = newsrv->puid = next_id;
6486 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6487 }
6488 next_id++;
6489 newsrv = newsrv->next;
6490 }
6491
Willy Tarreau20697042007-11-15 23:26:18 +01006492 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006493 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006494
Willy Tarreau62c3be22012-01-20 13:12:32 +01006495 /*
6496 * If this server supports a maxconn parameter, it needs a dedicated
6497 * tasks to fill the emptied slots when a connection leaves.
6498 * Also, resolve deferred tracking dependency if needed.
6499 */
6500 newsrv = curproxy->srv;
6501 while (newsrv != NULL) {
6502 if (newsrv->minconn > newsrv->maxconn) {
6503 /* Only 'minconn' was specified, or it was higher than or equal
6504 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6505 * this will avoid further useless expensive computations.
6506 */
6507 newsrv->maxconn = newsrv->minconn;
6508 } else if (newsrv->maxconn && !newsrv->minconn) {
6509 /* minconn was not specified, so we set it to maxconn */
6510 newsrv->minconn = newsrv->maxconn;
6511 }
6512
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006513#ifdef USE_OPENSSL
6514#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6515#define SSL_OP_NO_COMPRESSION 0
6516#endif
6517#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6518#define SSL_MODE_RELEASE_BUFFERS 0
6519#endif
6520#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6521#define SSL_OP_NO_COMPRESSION 0
6522#endif
6523 if (newsrv->use_ssl) {
6524 int ssloptions =
6525 SSL_OP_ALL | /* all known workarounds for bugs */
6526 SSL_OP_NO_SSLv2 |
6527 SSL_OP_NO_COMPRESSION;
6528 int sslmode =
6529 SSL_MODE_ENABLE_PARTIAL_WRITE |
6530 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6531 SSL_MODE_RELEASE_BUFFERS;
6532
6533 /* Initiate SSL context for current server */
6534 newsrv->ssl_ctx.reused_sess = NULL;
6535 newsrv->data = &ssl_sock;
6536 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6537 if(!newsrv->ssl_ctx.ctx) {
6538
6539 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6540 proxy_type_str(curproxy), curproxy->id,
6541 newsrv->id);
6542 cfgerr++;
6543 goto next_srv;
6544 }
6545
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006546 if (newsrv->ssl_ctx.nosslv3)
6547 ssloptions |= SSL_OP_NO_SSLv3;
6548 if (newsrv->ssl_ctx.notlsv1)
6549 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006550 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6551 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6552 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6553 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006554 if (newsrv->ssl_ctx.ciphers &&
6555 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6556 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6557 curproxy->id, newsrv->id,
6558 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6559 cfgerr++;
6560 goto next_srv;
6561 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006562 }
6563#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006564 if (newsrv->trackit) {
6565 struct proxy *px;
6566 struct server *srv;
6567 char *pname, *sname;
6568
6569 pname = newsrv->trackit;
6570 sname = strrchr(pname, '/');
6571
6572 if (sname)
6573 *sname++ = '\0';
6574 else {
6575 sname = pname;
6576 pname = NULL;
6577 }
6578
6579 if (pname) {
6580 px = findproxy(pname, PR_CAP_BE);
6581 if (!px) {
6582 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6583 proxy_type_str(curproxy), curproxy->id,
6584 newsrv->id, pname);
6585 cfgerr++;
6586 goto next_srv;
6587 }
6588 } else
6589 px = curproxy;
6590
6591 srv = findserver(px, sname);
6592 if (!srv) {
6593 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6594 proxy_type_str(curproxy), curproxy->id,
6595 newsrv->id, sname);
6596 cfgerr++;
6597 goto next_srv;
6598 }
6599
6600 if (!(srv->state & SRV_CHECKED)) {
6601 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6602 "tracking as it does not have checks enabled.\n",
6603 proxy_type_str(curproxy), curproxy->id,
6604 newsrv->id, px->id, srv->id);
6605 cfgerr++;
6606 goto next_srv;
6607 }
6608
6609 if (curproxy != px &&
6610 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6611 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6612 "tracking: disable-on-404 option inconsistency.\n",
6613 proxy_type_str(curproxy), curproxy->id,
6614 newsrv->id, px->id, srv->id);
6615 cfgerr++;
6616 goto next_srv;
6617 }
6618
6619 /* if the other server is forced disabled, we have to do the same here */
6620 if (srv->state & SRV_MAINTAIN) {
6621 newsrv->state |= SRV_MAINTAIN;
6622 newsrv->state &= ~SRV_RUNNING;
6623 newsrv->health = 0;
6624 }
6625
6626 newsrv->track = srv;
6627 newsrv->tracknext = srv->tracknext;
6628 srv->tracknext = newsrv;
6629
6630 free(newsrv->trackit);
6631 newsrv->trackit = NULL;
6632 }
6633 next_srv:
6634 newsrv = newsrv->next;
6635 }
6636
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006637 /* We have to initialize the server lookup mechanism depending
6638 * on what LB algorithm was choosen.
6639 */
6640
6641 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6642 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6643 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006644 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6645 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6646 init_server_map(curproxy);
6647 } else {
6648 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6649 fwrr_init_server_groups(curproxy);
6650 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006651 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006652
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006653 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006654 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6655 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6656 fwlc_init_server_tree(curproxy);
6657 } else {
6658 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6659 fas_init_server_tree(curproxy);
6660 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006661 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006662
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006663 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006664 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6665 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6666 chash_init_server_tree(curproxy);
6667 } else {
6668 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6669 init_server_map(curproxy);
6670 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006671 break;
6672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006673
6674 if (curproxy->options & PR_O_LOGASAP)
6675 curproxy->to_log &= ~LW_BYTES;
6676
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006677 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006678 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006679 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6680 proxy_type_str(curproxy), curproxy->id);
6681 err_code |= ERR_WARN;
6682 }
6683
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006684 if (curproxy->mode != PR_MODE_HTTP) {
6685 int optnum;
6686
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006687 if (curproxy->uri_auth) {
6688 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6689 proxy_type_str(curproxy), curproxy->id);
6690 err_code |= ERR_WARN;
6691 curproxy->uri_auth = NULL;
6692 }
6693
Willy Tarreau87cf5142011-08-19 22:57:24 +02006694 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006695 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6696 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6697 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006698 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006699 }
6700
6701 if (curproxy->options & PR_O_ORGTO) {
6702 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6703 "originalto", proxy_type_str(curproxy), curproxy->id);
6704 err_code |= ERR_WARN;
6705 curproxy->options &= ~PR_O_ORGTO;
6706 }
6707
6708 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6709 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6710 (curproxy->cap & cfg_opts[optnum].cap) &&
6711 (curproxy->options & cfg_opts[optnum].val)) {
6712 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6713 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6714 err_code |= ERR_WARN;
6715 curproxy->options &= ~cfg_opts[optnum].val;
6716 }
6717 }
6718
6719 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6720 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6721 (curproxy->cap & cfg_opts2[optnum].cap) &&
6722 (curproxy->options2 & cfg_opts2[optnum].val)) {
6723 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6724 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6725 err_code |= ERR_WARN;
6726 curproxy->options2 &= ~cfg_opts2[optnum].val;
6727 }
6728 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006729
Willy Tarreauefa5f512010-03-30 20:13:29 +02006730#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006731 if (curproxy->bind_hdr_occ) {
6732 curproxy->bind_hdr_occ = 0;
6733 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6734 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6735 err_code |= ERR_WARN;
6736 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006737#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006738 }
6739
Willy Tarreaubaaee002006-06-26 02:48:02 +02006740 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006741 * ensure that we're not cross-dressing a TCP server into HTTP.
6742 */
6743 newsrv = curproxy->srv;
6744 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006745 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006746 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6747 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006748 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006749 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006750
Willy Tarreau0cec3312011-10-31 13:49:26 +01006751 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6752 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6753 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6754 err_code |= ERR_WARN;
6755 }
6756
Willy Tarreauefa5f512010-03-30 20:13:29 +02006757#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006758 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6759 newsrv->bind_hdr_occ = 0;
6760 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6761 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6762 err_code |= ERR_WARN;
6763 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006764#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006765 newsrv = newsrv->next;
6766 }
6767
Willy Tarreauc1a21672009-08-16 22:37:44 +02006768 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006769 curproxy->accept = frontend_accept;
6770
Willy Tarreauc1a21672009-08-16 22:37:44 +02006771 if (curproxy->tcp_req.inspect_delay ||
6772 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006773 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006774
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006775 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006776 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006777 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006778 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006779
6780 /* both TCP and HTTP must check switching rules */
6781 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6782 }
6783
6784 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006785 if (curproxy->tcp_req.inspect_delay ||
6786 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6787 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6788
Emeric Brun97679e72010-09-23 17:56:44 +02006789 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6790 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6791
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006792 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006793 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006794 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006795 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006796
6797 /* If the backend does requires RDP cookie persistence, we have to
6798 * enable the corresponding analyser.
6799 */
6800 if (curproxy->options2 & PR_O2_RDPC_PRST)
6801 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6802 }
6803
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006804 listener = NULL;
6805 while (curproxy->listen) {
6806 struct listener *next;
6807
6808 next = curproxy->listen->next;
6809 curproxy->listen->next = listener;
6810 listener = curproxy->listen;
6811
6812 if (!next)
6813 break;
6814
6815 curproxy->listen = next;
6816 }
6817
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006818 /* Configure SSL for each bind line.
6819 * Note: if configuration fails at some point, the ->ctx member
6820 * remains NULL so that listeners can later detach.
6821 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006822 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6823 if (!bind_conf->is_ssl)
6824 continue;
6825#ifdef USE_OPENSSL
6826 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006827 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006828 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006829 cfgerr++;
6830 continue;
6831 }
6832
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006833 if (shared_context_init(global.tune.sslcachesize) < 0) {
6834 Alert("Unable to allocate SSL session cache.\n");
6835 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006836 continue;
6837 }
6838
Emeric Brunfc0421f2012-09-07 17:30:07 +02006839 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006840 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006841#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006842 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006843
Willy Tarreaue6b98942007-10-29 01:09:36 +01006844 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006845 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006846 listener = curproxy->listen;
6847 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006848 if (!listener->luid) {
6849 /* listener ID not set, use automatic numbering with first
6850 * spare entry starting with next_luid.
6851 */
6852 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6853 listener->conf.id.key = listener->luid = next_id;
6854 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006855 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006856 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006857
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006858 /* enable separate counters */
6859 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6860 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6861 if (!listener->name) {
6862 sprintf(trash, "sock-%d", listener->luid);
6863 listener->name = strdup(trash);
6864 }
6865 }
Emeric Brun6e159292012-05-18 16:32:13 +02006866#ifdef USE_OPENSSL
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006867 if (listener->bind_conf->is_ssl && listener->bind_conf->default_ctx)
6868 listener->data = &ssl_sock; /* SSL data layer */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006869#endif
Willy Tarreaue6b98942007-10-29 01:09:36 +01006870 if (curproxy->options & PR_O_TCP_NOLING)
6871 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006872 if (!listener->maxconn)
6873 listener->maxconn = curproxy->maxconn;
6874 if (!listener->backlog)
6875 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006876 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006877 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006878 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006879 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006880 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006881
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006882 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6883 listener->options |= LI_O_TCP_RULES;
6884
Willy Tarreaude3041d2010-05-31 10:56:17 +02006885 if (curproxy->mon_mask.s_addr)
6886 listener->options |= LI_O_CHK_MONNET;
6887
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006888 /* smart accept mode is automatic in HTTP mode */
6889 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006890 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006891 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6892 listener->options |= LI_O_NOQUICKACK;
6893
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006894 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006895 listener = listener->next;
6896 }
6897
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006898 /* Release unused SSL configs */
6899 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6900 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006901 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006902#ifdef USE_OPENSSL
6903 ssl_sock_free_all_ctx(bind_conf);
6904 free(bind_conf->ciphers);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006905#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006906 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006907
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006908 /* Check multi-process mode compatibility for the current proxy */
6909 if (global.nbproc > 1) {
6910 int nbproc = 0;
6911 if (curproxy->bind_proc) {
6912 int proc;
6913 for (proc = 0; proc < global.nbproc; proc++) {
6914 if (curproxy->bind_proc & (1 << proc)) {
6915 nbproc++;
6916 }
6917 }
6918 } else {
6919 nbproc = global.nbproc;
6920 }
6921 if (curproxy->table.peers.name) {
6922 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6923 curproxy->id);
6924 cfgerr++;
6925 }
6926 if (nbproc > 1) {
6927 if (curproxy->uri_auth) {
6928 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6929 curproxy->id);
6930 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6931 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6932 curproxy->id);
6933 }
6934 }
6935 if (curproxy->appsession_name) {
6936 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6937 curproxy->id);
6938 }
6939 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6940 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6941 curproxy->id);
6942 }
6943 }
6944 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006945
6946 /* create the task associated with the proxy */
6947 curproxy->task = task_new();
6948 if (curproxy->task) {
6949 curproxy->task->context = curproxy;
6950 curproxy->task->process = manage_proxy;
6951 /* no need to queue, it will be done automatically if some
6952 * listener gets limited.
6953 */
6954 curproxy->task->expire = TICK_ETERNITY;
6955 } else {
6956 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6957 curproxy->id);
6958 cfgerr++;
6959 }
6960
Willy Tarreaubaaee002006-06-26 02:48:02 +02006961 curproxy = curproxy->next;
6962 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006963
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006964 /* Check multi-process mode compatibility */
6965 if (global.nbproc > 1) {
6966 if (global.stats_fe) {
6967 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6968 }
6969 }
6970
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006971 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6972 struct auth_users *curuser;
6973 int g;
6974
6975 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6976 unsigned int group_mask = 0;
6977 char *group = NULL;
6978
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006979 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006980 continue;
6981
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006982 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006983
6984 for (g = 0; g < curuserlist->grpcnt; g++)
6985 if (!strcmp(curuserlist->groups[g], group))
6986 break;
6987
6988 if (g == curuserlist->grpcnt) {
6989 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6990 curuserlist->name, group, curuser->user);
6991 err_code |= ERR_ALERT | ERR_FATAL;
6992 goto out;
6993 }
6994
6995 group_mask |= (1 << g);
6996 }
6997
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006998 free(curuser->u.groups);
6999 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007000 }
7001
7002 for (g = 0; g < curuserlist->grpcnt; g++) {
7003 char *user = NULL;
7004
7005 if (!curuserlist->groupusers[g])
7006 continue;
7007
7008 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7009 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7010 if (!strcmp(curuser->user, user))
7011 break;
7012
7013 if (!curuser) {
7014 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7015 curuserlist->name, user, curuserlist->groups[g]);
7016 err_code |= ERR_ALERT | ERR_FATAL;
7017 goto out;
7018 }
7019
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007020 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007021 }
7022
7023 free(curuserlist->groupusers[g]);
7024 }
7025
7026 free(curuserlist->groupusers);
7027
7028#ifdef DEBUG_AUTH
7029 for (g = 0; g < curuserlist->grpcnt; g++) {
7030 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7031
7032 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007033 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007034 fprintf(stderr, " %s", curuser->user);
7035 }
7036
7037 fprintf(stderr, "\n");
7038 }
7039#endif
7040
Willy Tarreaufbb78422011-06-05 15:38:35 +02007041 }
7042
7043 /* automatically compute fullconn if not set. We must not do it in the
7044 * loop above because cross-references are not yet fully resolved.
7045 */
7046 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7047 /* If <fullconn> is not set, let's set it to 10% of the sum of
7048 * the possible incoming frontend's maxconns.
7049 */
7050 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7051 struct proxy *fe;
7052 int total = 0;
7053
7054 /* sum up the number of maxconns of frontends which
7055 * reference this backend at least once or which are
7056 * the same one ('listen').
7057 */
7058 for (fe = proxy; fe; fe = fe->next) {
7059 struct switching_rule *rule;
7060 struct hdr_exp *exp;
7061 int found = 0;
7062
7063 if (!(fe->cap & PR_CAP_FE))
7064 continue;
7065
7066 if (fe == curproxy) /* we're on a "listen" instance */
7067 found = 1;
7068
7069 if (fe->defbe.be == curproxy) /* "default_backend" */
7070 found = 1;
7071
7072 /* check if a "use_backend" rule matches */
7073 if (!found) {
7074 list_for_each_entry(rule, &fe->switching_rules, list) {
7075 if (rule->be.backend == curproxy) {
7076 found = 1;
7077 break;
7078 }
7079 }
7080 }
7081
7082 /* check if a "reqsetbe" rule matches */
7083 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7084 if (exp->action == ACT_SETBE &&
7085 (struct proxy *)exp->replace == curproxy) {
7086 found = 1;
7087 break;
7088 }
7089 }
7090
7091 /* now we've checked all possible ways to reference a backend
7092 * from a frontend.
7093 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007094 if (!found)
7095 continue;
7096 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007097 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007098 /* we have the sum of the maxconns in <total>. We only
7099 * keep 10% of that sum to set the default fullconn, with
7100 * a hard minimum of 1 (to avoid a divide by zero).
7101 */
7102 curproxy->fullconn = (total + 9) / 10;
7103 if (!curproxy->fullconn)
7104 curproxy->fullconn = 1;
7105 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007106 }
7107
Willy Tarreau056f5682010-06-06 15:51:11 +02007108 /* initialize stick-tables on backend capable proxies. This must not
7109 * be done earlier because the data size may be discovered while parsing
7110 * other proxies.
7111 */
7112 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007113 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007115 /*
7116 * Recount currently required checks.
7117 */
7118
7119 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7120 int optnum;
7121
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007122 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7123 if (curproxy->options & cfg_opts[optnum].val)
7124 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007125
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007126 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7127 if (curproxy->options2 & cfg_opts2[optnum].val)
7128 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007129 }
7130
Willy Tarreau122541c2011-09-07 21:24:49 +02007131 if (peers) {
7132 struct peers *curpeers = peers, **last;
7133 struct peer *p, *pb;
7134
7135 /* Remove all peers sections which don't have a valid listener.
7136 * This can happen when a peers section is never referenced and
7137 * does not contain a local peer.
7138 */
7139 last = &peers;
7140 while (*last) {
7141 curpeers = *last;
7142 if (curpeers->peers_fe) {
7143 last = &curpeers->next;
7144 continue;
7145 }
7146
7147 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7148 curpeers->id, localpeer);
7149
7150 p = curpeers->remote;
7151 while (p) {
7152 pb = p->next;
7153 free(p->id);
7154 free(p);
7155 p = pb;
7156 }
7157
7158 /* Destroy and unlink this curpeers section.
7159 * Note: curpeers is backed up into *last.
7160 */
7161 free(curpeers->id);
7162 curpeers = curpeers->next;
7163 free(*last);
7164 *last = curpeers;
7165 }
7166 }
7167
Willy Tarreauac1932d2011-10-24 19:14:41 +02007168 if (!global.tune.max_http_hdr)
7169 global.tune.max_http_hdr = MAX_HTTP_HDR;
7170
Willy Tarreau34eb6712011-10-24 18:15:04 +02007171 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007172 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007173 MEM_F_SHARED);
7174
Willy Tarreaubb925012009-07-23 13:36:36 +02007175 if (cfgerr > 0)
7176 err_code |= ERR_ALERT | ERR_FATAL;
7177 out:
7178 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007179}
7180
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007181/*
7182 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7183 * parsing sessions.
7184 */
7185void cfg_register_keywords(struct cfg_kw_list *kwl)
7186{
7187 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7188}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007189
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007190/*
7191 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7192 */
7193void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7194{
7195 LIST_DEL(&kwl->list);
7196 LIST_INIT(&kwl->list);
7197}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007198
7199/*
7200 * Local variables:
7201 * c-indent-level: 8
7202 * c-basic-offset: 8
7203 * End:
7204 */