blob: af89219c149449b4c81fb01d08f828900a8c6672 [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.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200193 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
194 * not NULL, it must be a valid pointer to either NULL or a freeable area that
195 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200197int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198{
199 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100200 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 int port, end;
202
203 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200204
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 while (next && *next) {
206 struct sockaddr_storage ss;
207
208 str = next;
209 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100210 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211 *next++ = 0;
212 }
213
Emeric Bruned760922010-10-22 17:59:25 +0200214 if (*str == '/') {
215 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
216 /* so compute max path */
217 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
218 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 +0200219
Emeric Bruned760922010-10-22 17:59:25 +0200220 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200221 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200222 goto fail;
223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200226 ss.ss_family = AF_UNIX;
227 if (global.unix_bind.prefix) {
228 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
229 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 }
Emeric Bruned760922010-10-22 17:59:25 +0200231 else {
232 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
233 }
234 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 }
236 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100237 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100239 ss2 = str2sa_range(str, &port, &end);
240 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200241 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 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) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200246 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 /* OK the address looks correct */
251 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
263
264 for (; port <= end; port++) {
265 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau4348fad2012-09-20 16:48:07 +0200266 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
267 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
268 l->frontend = curproxy;
269 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
271 l->fd = -1;
272 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200273 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100274 l->state = LI_INIT;
275
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100276 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 tcpv4_add_listener(l);
279 }
Emeric Bruned760922010-10-22 17:59:25 +0200280 else if (ss.ss_family == AF_INET6) {
281 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
282 tcpv6_add_listener(l);
283 }
284 else {
Emeric Bruned760922010-10-22 17:59:25 +0200285 uxst_add_listener(l);
286 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200288 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 } /* end for(port) */
291 } /* end while(next) */
292 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200293 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 fail:
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297}
298
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299/*
300 * Sends a warning if proxy <proxy> does not have at least one of the
301 * capabilities in <cap>. An optionnal <hint> may be added at the end
302 * of the warning to help the user. Returns 1 if a warning was emitted
303 * or 0 if the condition is valid.
304 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100305int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100306{
307 char *msg;
308
309 switch (cap) {
310 case PR_CAP_BE: msg = "no backend"; break;
311 case PR_CAP_FE: msg = "no frontend"; break;
312 case PR_CAP_RS: msg = "no ruleset"; break;
313 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
314 default: msg = "not enough"; break;
315 }
316
317 if (!(proxy->cap & cap)) {
318 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100319 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320 return 1;
321 }
322 return 0;
323}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324
Willy Tarreau61d18892009-03-31 10:49:21 +0200325/* Report a warning if a rule is placed after a 'block' rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100328int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200329{
330 if (!LIST_ISEMPTY(&proxy->block_cond)) {
331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
338/* Report a warning if a rule is placed after a reqrewrite rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100341int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200342{
343 if (proxy->req_exp) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a reqadd rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100354int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200355{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100356 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* Report a warning if a rule is placed after a redirect rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100367int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200368{
369 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
377/* Report a warning if a rule is placed after a 'use_backend' rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
382 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
390/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100391int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200392{
393 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
394 warnif_rule_after_reqadd(proxy, file, line, arg) ||
395 warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
399/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
403 warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
407/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100408int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200409{
410 return warnif_rule_after_redirect(proxy, file, line, arg) ||
411 warnif_rule_after_use_backend(proxy, file, line, arg);
412}
413
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100414/* Report it if a request ACL condition uses some response-only parameters. It
415 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
416 * Note that <cond> may be NULL and then will be ignored.
417 */
418static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
419{
420 struct acl *acl;
421
422 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
423 return 0;
424
425 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
426 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
427 file, line, acl ? acl->name : "(unknown)");
428 return ERR_WARN;
429}
430
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100431/* Report it if a request ACL condition uses some request-only volatile parameters.
432 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
433 * Note that <cond> may be NULL and then will be ignored.
434 */
435static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
436{
437 struct acl *acl;
438
439 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
440 return 0;
441
442 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
443 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
444 file, line, acl ? acl->name : "(unknown)");
445 return ERR_WARN;
446}
447
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100448
Willy Tarreaubaaee002006-06-26 02:48:02 +0200449/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 * parse a line in a <global> section. Returns the error code, 0 if OK, or
451 * any combination of :
452 * - ERR_ABORT: must abort ASAP
453 * - ERR_FATAL: we can continue parsing but not start the service
454 * - ERR_WARN: a warning has been emitted
455 * - ERR_ALERT: an alert has been emitted
456 * Only the two first ones can stop processing, the two others are just
457 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200459int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460{
Willy Tarreau058e9072009-07-20 09:30:05 +0200461 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200462 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463
464 if (!strcmp(args[0], "global")) { /* new section */
465 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 }
468 else if (!strcmp(args[0], "daemon")) {
469 global.mode |= MODE_DAEMON;
470 }
471 else if (!strcmp(args[0], "debug")) {
472 global.mode |= MODE_DEBUG;
473 }
474 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100475 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200477 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200479 }
480 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100481 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100484 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100486 else if (!strcmp(args[0], "nosplice")) {
487 global.tune.options &= ~GTUNE_USE_SPLICE;
488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200489 else if (!strcmp(args[0], "quiet")) {
490 global.mode |= MODE_QUIET;
491 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200492 else if (!strcmp(args[0], "tune.maxpollevents")) {
493 if (global.tune.maxpollevents != 0) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200495 err_code |= ERR_ALERT;
496 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200502 }
503 global.tune.maxpollevents = atol(args[1]);
504 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100505 else if (!strcmp(args[0], "tune.maxaccept")) {
506 if (global.tune.maxaccept != 0) {
507 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200508 err_code |= ERR_ALERT;
509 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100510 }
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100515 }
516 global.tune.maxaccept = atol(args[1]);
517 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200518 else if (!strcmp(args[0], "tune.chksize")) {
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.tune.chksize = atol(args[1]);
525 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200526#ifdef USE_OPENSSL
527 else if (!strcmp(args[0], "tune.sslcachesize")) {
528 if (*(args[1]) == 0) {
529 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
530 err_code |= ERR_ALERT | ERR_FATAL;
531 goto out;
532 }
533 global.tune.sslcachesize = atol(args[1]);
534 }
535#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200536 else if (!strcmp(args[0], "tune.bufsize")) {
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
541 }
542 global.tune.bufsize = atol(args[1]);
543 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
544 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200545 trashlen = global.tune.bufsize;
546 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200547 }
548 else if (!strcmp(args[0], "tune.maxrewrite")) {
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
553 }
554 global.tune.maxrewrite = atol(args[1]);
555 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
556 global.tune.maxrewrite = global.tune.bufsize / 2;
557 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100558 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
559 if (global.tune.client_rcvbuf != 0) {
560 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT;
562 goto out;
563 }
564 if (*(args[1]) == 0) {
565 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT | ERR_FATAL;
567 goto out;
568 }
569 global.tune.client_rcvbuf = atol(args[1]);
570 }
571 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
572 if (global.tune.server_rcvbuf != 0) {
573 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT;
575 goto out;
576 }
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582 global.tune.server_rcvbuf = atol(args[1]);
583 }
584 else if (!strcmp(args[0], "tune.sndbuf.client")) {
585 if (global.tune.client_sndbuf != 0) {
586 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT;
588 goto out;
589 }
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT | ERR_FATAL;
593 goto out;
594 }
595 global.tune.client_sndbuf = atol(args[1]);
596 }
597 else if (!strcmp(args[0], "tune.sndbuf.server")) {
598 if (global.tune.server_sndbuf != 0) {
599 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT;
601 goto out;
602 }
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.server_sndbuf = atol(args[1]);
609 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200610 else if (!strcmp(args[0], "tune.pipesize")) {
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.pipesize = atol(args[1]);
617 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200618 else if (!strcmp(args[0], "tune.http.maxhdr")) {
619 if (*(args[1]) == 0) {
620 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
621 err_code |= ERR_ALERT | ERR_FATAL;
622 goto out;
623 }
624 global.tune.max_http_hdr = atol(args[1]);
625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 else if (!strcmp(args[0], "uid")) {
627 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200628 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT;
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 }
632 if (*(args[1]) == 0) {
633 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT | ERR_FATAL;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 global.uid = atol(args[1]);
638 }
639 else if (!strcmp(args[0], "gid")) {
640 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200641 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200642 err_code |= ERR_ALERT;
643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
645 if (*(args[1]) == 0) {
646 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200647 err_code |= ERR_ALERT | ERR_FATAL;
648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649 }
650 global.gid = atol(args[1]);
651 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200652 /* user/group name handling */
653 else if (!strcmp(args[0], "user")) {
654 struct passwd *ha_user;
655 if (global.uid != 0) {
656 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200657 err_code |= ERR_ALERT;
658 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200659 }
660 errno = 0;
661 ha_user = getpwnam(args[1]);
662 if (ha_user != NULL) {
663 global.uid = (int)ha_user->pw_uid;
664 }
665 else {
666 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 +0200667 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 }
670 else if (!strcmp(args[0], "group")) {
671 struct group *ha_group;
672 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200673 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200674 err_code |= ERR_ALERT;
675 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200676 }
677 errno = 0;
678 ha_group = getgrnam(args[1]);
679 if (ha_group != NULL) {
680 global.gid = (int)ha_group->gr_gid;
681 }
682 else {
683 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 +0200684 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200685 }
686 }
687 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 else if (!strcmp(args[0], "nbproc")) {
689 if (global.nbproc != 0) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.nbproc = atol(args[1]);
700 }
701 else if (!strcmp(args[0], "maxconn")) {
702 if (global.maxconn != 0) {
703 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200704 err_code |= ERR_ALERT;
705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200706 }
707 if (*(args[1]) == 0) {
708 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 }
712 global.maxconn = atol(args[1]);
713#ifdef SYSTEM_MAXCONN
714 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
715 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);
716 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200717 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200718 }
719#endif /* SYSTEM_MAXCONN */
720 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200721 else if (!strcmp(args[0], "maxsslconn")) {
722#ifdef USE_OPENSSL
723 if (*(args[1]) == 0) {
724 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
725 err_code |= ERR_ALERT | ERR_FATAL;
726 goto out;
727 }
728 global.maxsslconn = atol(args[1]);
729#else
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735#endif
736 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200737 else if (!strcmp(args[0], "maxconnrate")) {
738 if (global.cps_lim != 0) {
739 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT;
741 goto out;
742 }
743 if (*(args[1]) == 0) {
744 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
747 }
748 global.cps_lim = atol(args[1]);
749 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100750 else if (!strcmp(args[0], "maxpipes")) {
751 if (global.maxpipes != 0) {
752 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200753 err_code |= ERR_ALERT;
754 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100755 }
756 if (*(args[1]) == 0) {
757 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100760 }
761 global.maxpipes = atol(args[1]);
762 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200763 else if (!strcmp(args[0], "ulimit-n")) {
764 if (global.rlimit_nofile != 0) {
765 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT;
767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 }
769 if (*(args[1]) == 0) {
770 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200771 err_code |= ERR_ALERT | ERR_FATAL;
772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773 }
774 global.rlimit_nofile = atol(args[1]);
775 }
776 else if (!strcmp(args[0], "chroot")) {
777 if (global.chroot != NULL) {
778 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 if (*(args[1]) == 0) {
783 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200786 }
787 global.chroot = strdup(args[1]);
788 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200789 else if (!strcmp(args[0], "description")) {
790 int i, len=0;
791 char *d;
792
793 if (!*args[1]) {
794 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
795 file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799
800 for(i=1; *args[i]; i++)
801 len += strlen(args[i])+1;
802
803 if (global.desc)
804 free(global.desc);
805
806 global.desc = d = (char *)calloc(1, len);
807
808 d += sprintf(d, "%s", args[1]);
809 for(i=2; *args[i]; i++)
810 d += sprintf(d, " %s", args[i]);
811 }
812 else if (!strcmp(args[0], "node")) {
813 int i;
814 char c;
815
816 for (i=0; args[1][i]; i++) {
817 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100818 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
819 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200820 break;
821 }
822
823 if (!i || args[1][i]) {
824 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
825 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
826 file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830
831 if (global.node)
832 free(global.node);
833
834 global.node = strdup(args[1]);
835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200836 else if (!strcmp(args[0], "pidfile")) {
837 if (global.pidfile != NULL) {
838 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200839 err_code |= ERR_ALERT;
840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841 }
842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847 global.pidfile = strdup(args[1]);
848 }
Emeric Bruned760922010-10-22 17:59:25 +0200849 else if (!strcmp(args[0], "unix-bind")) {
850 int cur_arg = 1;
851 while (*(args[cur_arg])) {
852 if (!strcmp(args[cur_arg], "prefix")) {
853 if (global.unix_bind.prefix != NULL) {
854 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
855 err_code |= ERR_ALERT;
856 cur_arg += 2;
857 continue;
858 }
859
860 if (*(args[cur_arg+1]) == 0) {
861 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865 global.unix_bind.prefix = strdup(args[cur_arg+1]);
866 cur_arg += 2;
867 continue;
868 }
869
870 if (!strcmp(args[cur_arg], "mode")) {
871
872 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
873 cur_arg += 2;
874 continue;
875 }
876
877 if (!strcmp(args[cur_arg], "uid")) {
878
879 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
880 cur_arg += 2;
881 continue;
882 }
883
884 if (!strcmp(args[cur_arg], "gid")) {
885
886 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
887 cur_arg += 2;
888 continue;
889 }
890
891 if (!strcmp(args[cur_arg], "user")) {
892 struct passwd *user;
893
894 user = getpwnam(args[cur_arg + 1]);
895 if (!user) {
896 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
897 file, linenum, args[0], args[cur_arg + 1 ]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901
902 global.unix_bind.ux.uid = user->pw_uid;
903 cur_arg += 2;
904 continue;
905 }
906
907 if (!strcmp(args[cur_arg], "group")) {
908 struct group *group;
909
910 group = getgrnam(args[cur_arg + 1]);
911 if (!group) {
912 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
913 file, linenum, args[0], args[cur_arg + 1 ]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917
918 global.unix_bind.ux.gid = group->gr_gid;
919 cur_arg += 2;
920 continue;
921 }
922
Willy Tarreaub48f9582011-09-05 01:17:06 +0200923 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200924 file, linenum, args[0]);
925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
927 }
928 }
William Lallemand0f99e342011-10-12 17:50:54 +0200929 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
930 /* delete previous herited or defined syslog servers */
931 struct logsrv *back;
932 struct logsrv *tmp;
933
934 if (*(args[1]) != 0) {
935 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939
940 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
941 LIST_DEL(&tmp->list);
942 free(tmp);
943 }
944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200946 struct logsrv *logsrv;
947
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 if (*(args[1]) == 0 || *(args[2]) == 0) {
949 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 }
William Lallemand0f99e342011-10-12 17:50:54 +0200953
954 logsrv = calloc(1, sizeof(struct logsrv));
955
956 logsrv->facility = get_log_facility(args[2]);
957 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200959 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200960 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 }
962
William Lallemand0f99e342011-10-12 17:50:54 +0200963 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200965 logsrv->level = get_log_level(args[3]);
966 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200968 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200969 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 }
971 }
972
William Lallemand0f99e342011-10-12 17:50:54 +0200973 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200974 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200975 logsrv->minlvl = get_log_level(args[4]);
976 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200977 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200979 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200980 }
981 }
982
Robert Tsai81ae1952007-12-05 10:47:29 +0100983 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100984 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100985 if (!sk) {
986 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100987 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100988 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200989 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100990 goto out;
991 }
William Lallemand0f99e342011-10-12 17:50:54 +0200992 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100993 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100994 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100995 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100996 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
997 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200998 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100999 goto out;
1000 }
William Lallemand0f99e342011-10-12 17:50:54 +02001001 logsrv->addr = *sk;
1002 if (!get_host_port(&logsrv->addr))
1003 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005
William Lallemand0f99e342011-10-12 17:50:54 +02001006 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001007 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001008 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1009 char *name;
1010 int len;
1011
1012 if (global.log_send_hostname != NULL) {
1013 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1014 err_code |= ERR_ALERT;
1015 goto out;
1016 }
1017
1018 if (*(args[1]))
1019 name = args[1];
1020 else
1021 name = hostname;
1022
1023 len = strlen(name);
1024
1025 /* We'll add a space after the name to respect the log format */
1026 free(global.log_send_hostname);
1027 global.log_send_hostname = malloc(len + 2);
1028 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1029 }
Kevinm48936af2010-12-22 16:08:21 +00001030 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1031 if (*(args[1]) == 0) {
1032 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035 }
1036 free(global.log_tag);
1037 global.log_tag = strdup(args[1]);
1038 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001039 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1040 if (global.spread_checks != 0) {
1041 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_ALERT;
1043 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001044 }
1045 if (*(args[1]) == 0) {
1046 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001049 }
1050 global.spread_checks = atol(args[1]);
1051 if (global.spread_checks < 0 || global.spread_checks > 50) {
1052 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001053 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 }
1056 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001057 struct cfg_kw_list *kwl;
1058 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001059 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001060
1061 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1062 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1063 if (kwl->kw[index].section != CFG_GLOBAL)
1064 continue;
1065 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1066 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001067 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001068 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau28a47d62012-09-18 20:02:48 +02001069 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001070 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001071 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001072 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001073 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001074 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001075 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001076 err_code |= ERR_WARN;
1077 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001078 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001080 }
1081 }
1082 }
1083
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001085 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001087
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001089 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091}
1092
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001093void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001095 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001096 defproxy.mode = PR_MODE_TCP;
1097 defproxy.state = PR_STNEW;
1098 defproxy.maxconn = cfg_maxpconn;
1099 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001100
1101 defproxy.defsrv.inter = DEF_CHKINTR;
1102 defproxy.defsrv.fastinter = 0;
1103 defproxy.defsrv.downinter = 0;
1104 defproxy.defsrv.rise = DEF_RISETIME;
1105 defproxy.defsrv.fall = DEF_FALLTIME;
1106 defproxy.defsrv.check_port = 0;
1107 defproxy.defsrv.maxqueue = 0;
1108 defproxy.defsrv.minconn = 0;
1109 defproxy.defsrv.maxconn = 0;
1110 defproxy.defsrv.slowstart = 0;
1111 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1112 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1113 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001114}
1115
Willy Tarreauade5ec42010-01-28 19:33:49 +01001116
1117static int create_cond_regex_rule(const char *file, int line,
1118 struct proxy *px, int dir, int action, int flags,
1119 const char *cmd, const char *reg, const char *repl,
1120 const char **cond_start)
1121{
1122 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001123 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001124 const char *err;
1125 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001126 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001127
1128 if (px == &defproxy) {
1129 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto err;
1132 }
1133
1134 if (*reg == 0) {
1135 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1136 err_code |= ERR_ALERT | ERR_FATAL;
1137 goto err;
1138 }
1139
1140 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1141 err_code |= ERR_WARN;
1142
Willy Tarreau5321c422010-01-28 20:35:13 +01001143 if (cond_start &&
1144 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001145 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1146 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1147 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto err;
1150 }
1151 }
1152 else if (cond_start && **cond_start) {
1153 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1154 file, line, cmd, *cond_start);
1155 err_code |= ERR_ALERT | ERR_FATAL;
1156 goto err;
1157 }
1158
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001159 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001160 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001161 else
1162 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001163
Willy Tarreauade5ec42010-01-28 19:33:49 +01001164 preg = calloc(1, sizeof(regex_t));
1165 if (!preg) {
1166 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1167 err_code = ERR_ALERT | ERR_FATAL;
1168 goto err;
1169 }
1170
1171 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1172 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1173 err_code = ERR_ALERT | ERR_FATAL;
1174 goto err;
1175 }
1176
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001177 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001178 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001179 if (repl && err) {
1180 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1181 file, line, cmd, *err);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto err;
1184 }
1185
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001186 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001187 err_code |= ERR_WARN;
1188
Willy Tarreauf4068b62012-05-08 17:37:49 +02001189 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001190 return err_code;
1191 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001192 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001193 free(preg);
1194 return err_code;
1195}
1196
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001198 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001199 * Returns the error code, 0 if OK, or any combination of :
1200 * - ERR_ABORT: must abort ASAP
1201 * - ERR_FATAL: we can continue parsing but not start the service
1202 * - ERR_WARN: a warning has been emitted
1203 * - ERR_ALERT: an alert has been emitted
1204 * Only the two first ones can stop processing, the two others are just
1205 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001206 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001207int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1208{
1209 static struct peers *curpeers = NULL;
1210 struct peer *newpeer = NULL;
1211 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001212 struct bind_conf *bind_conf;
1213 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001214 int err_code = 0;
1215
1216 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1217
1218 err = invalid_char(args[1]);
1219 if (err) {
1220 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1221 file, linenum, *err, args[0], args[1]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 }
1224
1225 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1226 /*
1227 * If there are two proxies with the same name only following
1228 * combinations are allowed:
1229 */
1230 if (strcmp(curpeers->id, args[1]) == 0) {
1231 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1232 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1233 err_code |= ERR_WARN;
1234 }
1235 }
1236
1237 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1238 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1239 err_code |= ERR_ALERT | ERR_ABORT;
1240 goto out;
1241 }
1242
1243 curpeers->next = peers;
1244 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001245 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001246 curpeers->conf.line = linenum;
1247 curpeers->last_change = now.tv_sec;
1248 curpeers->id = strdup(args[1]);
1249 }
1250 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1251 char *rport, *raddr;
1252 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001253 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001254 char *err_msg = NULL;
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;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001282 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001283 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 Tarreauf7bc57c2012-10-03 00:19:48 +02001309 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001310 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001311
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001312 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001313 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 Tarreau4348fad2012-09-20 16:48:07 +02001343
1344 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1345
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001346 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1347 if (err_msg && *err_msg) {
1348 indent_msg(&err_msg, 2);
1349 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1350 }
1351 else
1352 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1353 file, linenum, args[0], args[1], args[2]);
1354 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001355 err_code |= ERR_FATAL;
1356 goto out;
1357 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001358
1359 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1360 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1361 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1362 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1363 l->accept = session_accept;
1364 l->handler = process_session;
1365 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1366 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1367 global.maxsock += l->maxconn;
1368 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001369 }
1370 }
1371 } /* neither "peer" nor "peers" */
1372 else if (*args[0] != 0) {
1373 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
1376 }
1377
1378out:
1379 return err_code;
1380}
1381
1382
Willy Tarreau3842f002009-06-14 11:39:52 +02001383int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384{
1385 static struct proxy *curproxy = NULL;
1386 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001387 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001388 int rc;
1389 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001390 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001391 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001392 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001393 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001394 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395
Willy Tarreau977b8e42006-12-29 14:19:17 +01001396 if (!strcmp(args[0], "listen"))
1397 rc = PR_CAP_LISTEN;
1398 else if (!strcmp(args[0], "frontend"))
1399 rc = PR_CAP_FE | PR_CAP_RS;
1400 else if (!strcmp(args[0], "backend"))
1401 rc = PR_CAP_BE | PR_CAP_RS;
1402 else if (!strcmp(args[0], "ruleset"))
1403 rc = PR_CAP_RS;
1404 else
1405 rc = PR_CAP_NONE;
1406
1407 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 if (!*args[1]) {
1409 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1410 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1411 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001412 err_code |= ERR_ALERT | ERR_ABORT;
1413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001415
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001416 err = invalid_char(args[1]);
1417 if (err) {
1418 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1419 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001420 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001421 }
1422
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001423 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1424 /*
1425 * If there are two proxies with the same name only following
1426 * combinations are allowed:
1427 *
1428 * listen backend frontend ruleset
1429 * listen - - - -
1430 * backend - - OK -
1431 * frontend - OK - -
1432 * ruleset - - - -
1433 */
1434
1435 if (!strcmp(curproxy->id, args[1]) &&
1436 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1437 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001438 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1439 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1440 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001441 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001442 }
1443 }
1444
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1446 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001447 err_code |= ERR_ALERT | ERR_ABORT;
1448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001450
Willy Tarreau97cb7802010-01-03 20:23:58 +01001451 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 curproxy->next = proxy;
1453 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001454 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001455 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001456 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001458 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459
1460 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001461 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001462 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001463 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001464
Willy Tarreau4348fad2012-09-20 16:48:07 +02001465 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1466
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001467 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1468 if (err_msg && *err_msg) {
1469 indent_msg(&err_msg, 2);
1470 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1471 }
1472 else
1473 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1474 file, linenum, args[0], args[1], args[2]);
1475 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001476 err_code |= ERR_FATAL;
1477 goto out;
1478 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001479
Willy Tarreau4348fad2012-09-20 16:48:07 +02001480 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001481 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 }
1484
1485 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001486 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001487 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001488
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001491 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001492 curproxy->no_options = defproxy.no_options;
1493 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001494 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001495 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001496 curproxy->except_net = defproxy.except_net;
1497 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001498 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001499 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001501 if (defproxy.fwdfor_hdr_len) {
1502 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1503 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1504 }
1505
Willy Tarreaub86db342009-11-30 11:50:16 +01001506 if (defproxy.orgto_hdr_len) {
1507 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1508 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1509 }
1510
Mark Lamourinec2247f02012-01-04 13:02:01 -05001511 if (defproxy.server_id_hdr_len) {
1512 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1513 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1514 }
1515
Willy Tarreau977b8e42006-12-29 14:19:17 +01001516 if (curproxy->cap & PR_CAP_FE) {
1517 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001518 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001519 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001520
1521 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001522 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1523 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524
1525 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527
Willy Tarreau977b8e42006-12-29 14:19:17 +01001528 if (curproxy->cap & PR_CAP_BE) {
1529 curproxy->fullconn = defproxy.fullconn;
1530 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001532 if (defproxy.check_req) {
1533 curproxy->check_req = calloc(1, defproxy.check_len);
1534 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1535 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001536 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001538 if (defproxy.expect_str) {
1539 curproxy->expect_str = strdup(defproxy.expect_str);
1540 if (defproxy.expect_regex) {
1541 /* note: this regex is known to be valid */
1542 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1543 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1544 }
1545 }
1546
Willy Tarreau67402132012-05-31 20:40:20 +02001547 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001548 if (defproxy.cookie_name)
1549 curproxy->cookie_name = strdup(defproxy.cookie_name);
1550 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001551 if (defproxy.cookie_domain)
1552 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001553
Willy Tarreau31936852010-10-06 16:59:56 +02001554 if (defproxy.cookie_maxidle)
1555 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1556
1557 if (defproxy.cookie_maxlife)
1558 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1559
Emeric Brun647caf12009-06-30 17:57:00 +02001560 if (defproxy.rdp_cookie_name)
1561 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1562 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1563
Willy Tarreau01732802007-11-01 22:48:15 +01001564 if (defproxy.url_param_name)
1565 curproxy->url_param_name = strdup(defproxy.url_param_name);
1566 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001567
Benoitaffb4812009-03-25 13:02:10 +01001568 if (defproxy.hh_name)
1569 curproxy->hh_name = strdup(defproxy.hh_name);
1570 curproxy->hh_len = defproxy.hh_len;
1571 curproxy->hh_match_domain = defproxy.hh_match_domain;
1572
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001573 if (defproxy.iface_name)
1574 curproxy->iface_name = strdup(defproxy.iface_name);
1575 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001576 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001578 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001579 if (defproxy.capture_name)
1580 curproxy->capture_name = strdup(defproxy.capture_name);
1581 curproxy->capture_namelen = defproxy.capture_namelen;
1582 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584
Willy Tarreau977b8e42006-12-29 14:19:17 +01001585 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001586 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001587 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001588 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001589 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 curproxy->uri_auth = defproxy.uri_auth;
1591 curproxy->mon_net = defproxy.mon_net;
1592 curproxy->mon_mask = defproxy.mon_mask;
1593 if (defproxy.monitor_uri)
1594 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1595 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001596 if (defproxy.defbe.name)
1597 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001598
1599 /* get either a pointer to the logformat string or a copy of it */
1600 curproxy->logformat_string = defproxy.logformat_string;
1601 if (curproxy->logformat_string &&
1602 curproxy->logformat_string != default_http_log_format &&
1603 curproxy->logformat_string != default_tcp_log_format &&
1604 curproxy->logformat_string != clf_http_log_format)
1605 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001606 }
1607
1608 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001609 curproxy->timeout.connect = defproxy.timeout.connect;
1610 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001611 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001612 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001613 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001614 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001615 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001616 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001617 curproxy->source_addr = defproxy.source_addr;
1618 }
1619
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001621
1622 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001623 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001624 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001625 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001626 LIST_INIT(&node->list);
1627 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1628 }
1629
Willy Tarreau196729e2012-05-31 19:30:26 +02001630 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1631 if (curproxy->uniqueid_format_string)
1632 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001633
1634 /* copy default header unique id */
1635 if (defproxy.header_unique_id)
1636 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1637
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001639 curproxy->conf.used_listener_id = EB_ROOT;
1640 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001641
Willy Tarreau93893792009-07-23 13:19:11 +02001642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001643 }
1644 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1645 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001646 /* FIXME-20070101: we should do this too at the end of the
1647 * config parsing to free all default values.
1648 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001649 free(defproxy.check_req);
1650 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001651 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001652 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001653 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001654 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001655 free(defproxy.capture_name);
1656 free(defproxy.monitor_uri);
1657 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001658 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001659 free(defproxy.fwdfor_hdr_name);
1660 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001661 free(defproxy.orgto_hdr_name);
1662 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001663 free(defproxy.server_id_hdr_name);
1664 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001665 free(defproxy.expect_str);
1666 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001667
Willy Tarreau39b06652012-06-01 10:58:06 +02001668 if (defproxy.logformat_string != default_http_log_format &&
1669 defproxy.logformat_string != default_tcp_log_format &&
1670 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001671 free(defproxy.logformat_string);
1672
1673 free(defproxy.uniqueid_format_string);
1674
Willy Tarreaua534fea2008-08-03 12:19:50 +02001675 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001676 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001677
Willy Tarreaubaaee002006-06-26 02:48:02 +02001678 /* we cannot free uri_auth because it might already be used */
1679 init_default_instance();
1680 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001681 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 }
1684 else if (curproxy == NULL) {
1685 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 }
1689
Willy Tarreau977b8e42006-12-29 14:19:17 +01001690
1691 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001692 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001693 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001694 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001695 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001696
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 if (curproxy == &defproxy) {
1698 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001701 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001703 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704
Emeric Bruned760922010-10-22 17:59:25 +02001705 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001706 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001708 err_code |= ERR_ALERT | ERR_FATAL;
1709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001711
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001712 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001713 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001714
1715 /* NOTE: the following line might create several listeners if there
1716 * are comma-separated IPs or port ranges. So all further processing
1717 * will have to be applied to all listeners created after last_listen.
1718 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001719 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1720 if (err_msg && *err_msg) {
1721 indent_msg(&err_msg, 2);
1722 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1723 }
1724 else
1725 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1726 file, linenum, args[0], args[1]);
1727 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001731
Willy Tarreau4348fad2012-09-20 16:48:07 +02001732 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1733 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001734 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001735 }
1736
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001737 cur_arg = 2;
1738 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001739 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001740 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001741 char *err;
1742
Willy Tarreau26982662012-09-12 23:17:10 +02001743 kw = bind_find_kw(args[cur_arg]);
1744 if (kw) {
1745 char *err = NULL;
1746 int code;
1747
1748 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001749 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1750 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001751 cur_arg += 1 + kw->skip ;
1752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
1754 }
1755
Willy Tarreau4348fad2012-09-20 16:48:07 +02001756 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001757 err_code |= code;
1758
1759 if (code) {
1760 if (err && *err) {
1761 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001762 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001763 }
1764 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001765 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1766 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001767 if (code & ERR_FATAL) {
1768 free(err);
1769 cur_arg += 1 + kw->skip;
1770 goto out;
1771 }
1772 }
1773 free(err);
1774 cur_arg += 1 + kw->skip;
1775 continue;
1776 }
1777
Willy Tarreau8638f482012-09-18 18:01:17 +02001778 err = NULL;
1779 if (!bind_dumped) {
1780 bind_dump_kws(&err);
1781 indent_msg(&err, 4);
1782 bind_dumped = 1;
1783 }
1784
1785 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1786 file, linenum, args[0], args[1], args[cur_arg],
1787 err ? " Registered keywords :" : "", err ? err : "");
1788 free(err);
1789
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001792 }
Willy Tarreau93893792009-07-23 13:19:11 +02001793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 }
1795 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1796 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1797 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1798 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001799 err_code |= ERR_ALERT | ERR_FATAL;
1800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001803 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001804
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805 /* flush useless bits */
1806 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001808 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001809 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001811 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001812
Willy Tarreau1c47f852006-07-09 08:22:27 +02001813 if (!*args[1]) {
1814 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1815 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001818 }
1819
Willy Tarreaua534fea2008-08-03 12:19:50 +02001820 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001821 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001822 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001823 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001824 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1825
Willy Tarreau93893792009-07-23 13:19:11 +02001826 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001828 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1829 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1830 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1831 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1832 else {
1833 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 }
1837 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001838 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001839 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001840
1841 if (curproxy == &defproxy) {
1842 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1843 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001846 }
1847
1848 if (!*args[1]) {
1849 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1850 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001853 }
1854
1855 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001856 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001857
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001858 if (curproxy->uuid <= 0) {
1859 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001860 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001861 err_code |= ERR_ALERT | ERR_FATAL;
1862 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001863 }
1864
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001865 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1866 if (node) {
1867 struct proxy *target = container_of(node, struct proxy, conf.id);
1868 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1869 file, linenum, proxy_type_str(curproxy), curproxy->id,
1870 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1871 err_code |= ERR_ALERT | ERR_FATAL;
1872 goto out;
1873 }
1874 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001875 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001876 else if (!strcmp(args[0], "description")) {
1877 int i, len=0;
1878 char *d;
1879
Cyril Bonté99ed3272010-01-24 23:29:44 +01001880 if (curproxy == &defproxy) {
1881 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1882 file, linenum, args[0]);
1883 err_code |= ERR_ALERT | ERR_FATAL;
1884 goto out;
1885 }
1886
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001887 if (!*args[1]) {
1888 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1889 file, linenum, args[0]);
1890 return -1;
1891 }
1892
1893 for(i=1; *args[i]; i++)
1894 len += strlen(args[i])+1;
1895
1896 d = (char *)calloc(1, len);
1897 curproxy->desc = d;
1898
1899 d += sprintf(d, "%s", args[1]);
1900 for(i=2; *args[i]; i++)
1901 d += sprintf(d, " %s", args[i]);
1902
1903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1905 curproxy->state = PR_STSTOPPED;
1906 }
1907 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1908 curproxy->state = PR_STNEW;
1909 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001910 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1911 int cur_arg = 1;
1912 unsigned int set = 0;
1913
1914 while (*args[cur_arg]) {
1915 int u;
1916 if (strcmp(args[cur_arg], "all") == 0) {
1917 set = 0;
1918 break;
1919 }
1920 else if (strcmp(args[cur_arg], "odd") == 0) {
1921 set |= 0x55555555;
1922 }
1923 else if (strcmp(args[cur_arg], "even") == 0) {
1924 set |= 0xAAAAAAAA;
1925 }
1926 else {
1927 u = str2uic(args[cur_arg]);
1928 if (u < 1 || u > 32) {
1929 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001933 }
1934 if (u > global.nbproc) {
1935 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1936 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001937 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001938 }
1939 set |= 1 << (u - 1);
1940 }
1941 cur_arg++;
1942 }
1943 curproxy->bind_proc = set;
1944 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001945 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001946 if (curproxy == &defproxy) {
1947 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001950 }
1951
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001952 err = invalid_char(args[1]);
1953 if (err) {
1954 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1955 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001956 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001957 }
1958
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001959 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
1960 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
1961 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02001962 err_code |= ERR_ALERT | ERR_FATAL;
1963 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001964 }
1965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1967 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968
Willy Tarreau977b8e42006-12-29 14:19:17 +01001969 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001970 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001971
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 if (*(args[1]) == 0) {
1973 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1974 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001978
Willy Tarreau67402132012-05-31 20:40:20 +02001979 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001980 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001981 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001982 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 curproxy->cookie_name = strdup(args[1]);
1984 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001985
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986 cur_arg = 2;
1987 while (*(args[cur_arg])) {
1988 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001989 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990 }
1991 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001992 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 }
1994 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001995 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001996 }
1997 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001998 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 }
2000 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002001 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002003 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002004 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002005 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002006 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002007 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002009 else if (!strcmp(args[cur_arg], "httponly")) {
2010 curproxy->ck_opts |= PR_CK_HTTPONLY;
2011 }
2012 else if (!strcmp(args[cur_arg], "secure")) {
2013 curproxy->ck_opts |= PR_CK_SECURE;
2014 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002015 else if (!strcmp(args[cur_arg], "domain")) {
2016 if (!*args[cur_arg + 1]) {
2017 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2018 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002021 }
2022
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002023 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002024 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002025 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2026 " dots nor does not start with a dot."
2027 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002028 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002029 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002030 }
2031
2032 err = invalid_domainchar(args[cur_arg + 1]);
2033 if (err) {
2034 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2035 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002036 err_code |= ERR_ALERT | ERR_FATAL;
2037 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002038 }
2039
Willy Tarreau68a897b2009-12-03 23:28:34 +01002040 if (!curproxy->cookie_domain) {
2041 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2042 } else {
2043 /* one domain was already specified, add another one by
2044 * building the string which will be returned along with
2045 * the cookie.
2046 */
2047 char *new_ptr;
2048 int new_len = strlen(curproxy->cookie_domain) +
2049 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2050 new_ptr = malloc(new_len);
2051 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2052 free(curproxy->cookie_domain);
2053 curproxy->cookie_domain = new_ptr;
2054 }
Willy Tarreau31936852010-10-06 16:59:56 +02002055 cur_arg++;
2056 }
2057 else if (!strcmp(args[cur_arg], "maxidle")) {
2058 unsigned int maxidle;
2059 const char *res;
2060
2061 if (!*args[cur_arg + 1]) {
2062 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2063 file, linenum, args[cur_arg]);
2064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
2066 }
2067
2068 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2069 if (res) {
2070 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2071 file, linenum, *res, args[cur_arg]);
2072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
2074 }
2075 curproxy->cookie_maxidle = maxidle;
2076 cur_arg++;
2077 }
2078 else if (!strcmp(args[cur_arg], "maxlife")) {
2079 unsigned int maxlife;
2080 const char *res;
2081
2082 if (!*args[cur_arg + 1]) {
2083 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2084 file, linenum, args[cur_arg]);
2085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
2087 }
2088
2089 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2090 if (res) {
2091 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2092 file, linenum, *res, args[cur_arg]);
2093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
2095 }
2096 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002097 cur_arg++;
2098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002100 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 +02002101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 }
2105 cur_arg++;
2106 }
Willy Tarreau67402132012-05-31 20:40:20 +02002107 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002108 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2109 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 }
2112
Willy Tarreau67402132012-05-31 20:40:20 +02002113 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2115 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002116 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002118
Willy Tarreau67402132012-05-31 20:40:20 +02002119 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002120 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2121 file, linenum);
2122 err_code |= ERR_ALERT | ERR_FATAL;
2123 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002124 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002125 else if (!strcmp(args[0], "persist")) { /* persist */
2126 if (*(args[1]) == 0) {
2127 Alert("parsing [%s:%d] : missing persist method.\n",
2128 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
2130 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002131 }
2132
2133 if (!strncmp(args[1], "rdp-cookie", 10)) {
2134 curproxy->options2 |= PR_O2_RDPC_PRST;
2135
Emeric Brunb982a3d2010-01-04 15:45:53 +01002136 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002137 const char *beg, *end;
2138
2139 beg = args[1] + 11;
2140 end = strchr(beg, ')');
2141
2142 if (!end || end == beg) {
2143 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2144 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002145 err_code |= ERR_ALERT | ERR_FATAL;
2146 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002147 }
2148
2149 free(curproxy->rdp_cookie_name);
2150 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2151 curproxy->rdp_cookie_len = end-beg;
2152 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002153 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002154 free(curproxy->rdp_cookie_name);
2155 curproxy->rdp_cookie_name = strdup("msts");
2156 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2157 }
2158 else { /* syntax */
2159 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2160 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002161 err_code |= ERR_ALERT | ERR_FATAL;
2162 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002163 }
2164 }
2165 else {
2166 Alert("parsing [%s:%d] : unknown persist method.\n",
2167 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002170 }
2171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002173 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002175 if (curproxy == &defproxy) {
2176 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
2179 }
2180
Willy Tarreau977b8e42006-12-29 14:19:17 +01002181 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002183
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002185 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 }
2190 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002191 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 curproxy->appsession_name = strdup(args[1]);
2193 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2194 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002195 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2196 if (err) {
2197 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2198 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002201 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002202 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002203
Willy Tarreau51041c72007-09-09 21:56:53 +02002204 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2205 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002206 err_code |= ERR_ALERT | ERR_ABORT;
2207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002208 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002209
2210 cur_arg = 6;
2211 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002212 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2213 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002214 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002215 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002216 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002217 } else if (!strcmp(args[cur_arg], "prefix")) {
2218 curproxy->options2 |= PR_O2_AS_PFX;
2219 } else if (!strcmp(args[cur_arg], "mode")) {
2220 if (!*args[cur_arg + 1]) {
2221 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2222 file, linenum, args[0], args[cur_arg]);
2223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
2225 }
2226
2227 cur_arg++;
2228 if (!strcmp(args[cur_arg], "query-string")) {
2229 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2230 curproxy->options2 |= PR_O2_AS_M_QS;
2231 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2232 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2233 curproxy->options2 |= PR_O2_AS_M_PP;
2234 } else {
2235 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
2238 }
2239 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002240 cur_arg++;
2241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 } /* Url App Session */
2243 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002244 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002245 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002246
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002248 if (curproxy == &defproxy) {
2249 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
2252 }
2253
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 if (*(args[4]) == 0) {
2255 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2256 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002260 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 curproxy->capture_name = strdup(args[2]);
2262 curproxy->capture_namelen = strlen(curproxy->capture_name);
2263 curproxy->capture_len = atol(args[4]);
2264 if (curproxy->capture_len >= CAPTURE_LEN) {
2265 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2266 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002267 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 curproxy->capture_len = CAPTURE_LEN - 1;
2269 }
2270 curproxy->to_log |= LW_COOKIE;
2271 }
2272 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2273 struct cap_hdr *hdr;
2274
2275 if (curproxy == &defproxy) {
2276 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 +02002277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }
2280
2281 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2282 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2283 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 }
2287
2288 hdr = calloc(sizeof(struct cap_hdr), 1);
2289 hdr->next = curproxy->req_cap;
2290 hdr->name = strdup(args[3]);
2291 hdr->namelen = strlen(args[3]);
2292 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002293 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 hdr->index = curproxy->nb_req_cap++;
2295 curproxy->req_cap = hdr;
2296 curproxy->to_log |= LW_REQHDR;
2297 }
2298 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2299 struct cap_hdr *hdr;
2300
2301 if (curproxy == &defproxy) {
2302 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 +02002303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 }
2306
2307 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2308 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2309 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 }
2313 hdr = calloc(sizeof(struct cap_hdr), 1);
2314 hdr->next = curproxy->rsp_cap;
2315 hdr->name = strdup(args[3]);
2316 hdr->namelen = strlen(args[3]);
2317 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002318 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 hdr->index = curproxy->nb_rsp_cap++;
2320 curproxy->rsp_cap = hdr;
2321 curproxy->to_log |= LW_RSPHDR;
2322 }
2323 else {
2324 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2325 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 }
2329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002331 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002332 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002333
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 if (*(args[1]) == 0) {
2335 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2336 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 }
2340 curproxy->conn_retries = atol(args[1]);
2341 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002342 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002343 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002344
2345 if (curproxy == &defproxy) {
2346 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350
Willy Tarreauff011f22011-01-06 17:51:27 +01002351 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 +01002352 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2353 file, linenum, args[0]);
2354 err_code |= ERR_WARN;
2355 }
2356
Willy Tarreauff011f22011-01-06 17:51:27 +01002357 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002358
Willy Tarreauff011f22011-01-06 17:51:27 +01002359 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002360 err_code |= ERR_ALERT | ERR_ABORT;
2361 goto out;
2362 }
2363
Willy Tarreauff011f22011-01-06 17:51:27 +01002364 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2365 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002366 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002367 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2368 /* set the header name and length into the proxy structure */
2369 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2370 err_code |= ERR_WARN;
2371
2372 if (!*args[1]) {
2373 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2374 file, linenum, args[0]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378
2379 /* set the desired header name */
2380 free(curproxy->server_id_hdr_name);
2381 curproxy->server_id_hdr_name = strdup(args[1]);
2382 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2383 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002384 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002385 if (curproxy == &defproxy) {
2386 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002389 }
2390
Willy Tarreauef6494c2010-01-28 17:12:36 +01002391 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002392 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2393 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002396 }
2397
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002398 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2399 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2400 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002403 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002404
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002405 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002406 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002407 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002408 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002409 struct redirect_rule *rule;
2410 int cur_arg;
2411 int type = REDIRECT_TYPE_NONE;
2412 int code = 302;
2413 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002414 char *cookie = NULL;
2415 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002416 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002417
Cyril Bonté99ed3272010-01-24 23:29:44 +01002418 if (curproxy == &defproxy) {
2419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
2422 }
2423
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002424 cur_arg = 1;
2425 while (*(args[cur_arg])) {
2426 if (!strcmp(args[cur_arg], "location")) {
2427 if (!*args[cur_arg + 1]) {
2428 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2429 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002432 }
2433
2434 type = REDIRECT_TYPE_LOCATION;
2435 cur_arg++;
2436 destination = args[cur_arg];
2437 }
2438 else if (!strcmp(args[cur_arg], "prefix")) {
2439 if (!*args[cur_arg + 1]) {
2440 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2441 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002444 }
2445
2446 type = REDIRECT_TYPE_PREFIX;
2447 cur_arg++;
2448 destination = args[cur_arg];
2449 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002450 else if (!strcmp(args[cur_arg], "scheme")) {
2451 if (!*args[cur_arg + 1]) {
2452 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2453 file, linenum, args[0], args[cur_arg]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457
2458 type = REDIRECT_TYPE_SCHEME;
2459 cur_arg++;
2460 destination = args[cur_arg];
2461 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002462 else if (!strcmp(args[cur_arg], "set-cookie")) {
2463 if (!*args[cur_arg + 1]) {
2464 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2465 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002468 }
2469
2470 cur_arg++;
2471 cookie = args[cur_arg];
2472 cookie_set = 1;
2473 }
2474 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2475 if (!*args[cur_arg + 1]) {
2476 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2477 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002480 }
2481
2482 cur_arg++;
2483 cookie = args[cur_arg];
2484 cookie_set = 0;
2485 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002486 else if (!strcmp(args[cur_arg],"code")) {
2487 if (!*args[cur_arg + 1]) {
2488 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2489 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002492 }
2493 cur_arg++;
2494 code = atol(args[cur_arg]);
2495 if (code < 301 || code > 303) {
2496 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2497 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002500 }
2501 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002502 else if (!strcmp(args[cur_arg],"drop-query")) {
2503 flags |= REDIRECT_FLAG_DROP_QS;
2504 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002505 else if (!strcmp(args[cur_arg],"append-slash")) {
2506 flags |= REDIRECT_FLAG_APPEND_SLASH;
2507 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002508 else if (strcmp(args[cur_arg], "if") == 0 ||
2509 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002510 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002511 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002512 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2513 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
2516 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002517 break;
2518 }
2519 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002520 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 +02002521 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002524 }
2525 cur_arg++;
2526 }
2527
2528 if (type == REDIRECT_TYPE_NONE) {
2529 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2530 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002533 }
2534
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002535 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2536 rule->cond = cond;
2537 rule->rdr_str = strdup(destination);
2538 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002539 if (cookie) {
2540 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002541 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002542 */
2543 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002544 if (cookie_set) {
2545 rule->cookie_str = malloc(rule->cookie_len + 10);
2546 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2547 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2548 rule->cookie_len += 9;
2549 } else {
2550 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002551 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002552 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2553 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002554 }
2555 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002556 rule->type = type;
2557 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002558 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002559 LIST_INIT(&rule->list);
2560 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002561 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2562 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002563 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002564 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002565 struct switching_rule *rule;
2566
Willy Tarreaub099aca2008-10-12 17:26:37 +02002567 if (curproxy == &defproxy) {
2568 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002571 }
2572
Willy Tarreau55ea7572007-06-17 19:56:27 +02002573 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002575
2576 if (*(args[1]) == 0) {
2577 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002580 }
2581
Willy Tarreauef6494c2010-01-28 17:12:36 +01002582 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002583 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002587 }
2588
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002589 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2590 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2591 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002592 err_code |= ERR_ALERT | ERR_FATAL;
2593 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002594 }
2595
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002596 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002597
Willy Tarreau55ea7572007-06-17 19:56:27 +02002598 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2599 rule->cond = cond;
2600 rule->be.name = strdup(args[1]);
2601 LIST_INIT(&rule->list);
2602 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2603 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002604 else if (strcmp(args[0], "use-server") == 0) {
2605 struct server_rule *rule;
2606
2607 if (curproxy == &defproxy) {
2608 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
2611 }
2612
2613 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2614 err_code |= ERR_WARN;
2615
2616 if (*(args[1]) == 0) {
2617 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
2620 }
2621
2622 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2623 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2624 file, linenum, args[0]);
2625 err_code |= ERR_ALERT | ERR_FATAL;
2626 goto out;
2627 }
2628
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002629 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2630 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2631 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
2634 }
2635
2636 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2637
2638 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2639 rule->cond = cond;
2640 rule->srv.name = strdup(args[1]);
2641 LIST_INIT(&rule->list);
2642 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2643 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2644 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002645 else if ((!strcmp(args[0], "force-persist")) ||
2646 (!strcmp(args[0], "ignore-persist"))) {
2647 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002648
2649 if (curproxy == &defproxy) {
2650 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2651 err_code |= ERR_ALERT | ERR_FATAL;
2652 goto out;
2653 }
2654
2655 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2656 err_code |= ERR_WARN;
2657
Willy Tarreauef6494c2010-01-28 17:12:36 +01002658 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002659 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2660 file, linenum, args[0]);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002665 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2666 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2667 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
2670 }
2671
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002672 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002673
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002674 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002675 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002676 if (!strcmp(args[0], "force-persist")) {
2677 rule->type = PERSIST_TYPE_FORCE;
2678 } else {
2679 rule->type = PERSIST_TYPE_IGNORE;
2680 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002681 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002682 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002683 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002684 else if (!strcmp(args[0], "stick-table")) {
2685 int myidx = 1;
2686
Emeric Brun32da3c42010-09-23 18:39:19 +02002687 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002688 curproxy->table.type = (unsigned int)-1;
2689 while (*args[myidx]) {
2690 const char *err;
2691
2692 if (strcmp(args[myidx], "size") == 0) {
2693 myidx++;
2694 if (!*(args[myidx])) {
2695 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2696 file, linenum, args[myidx-1]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2701 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2702 file, linenum, *err, args[myidx-1]);
2703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
2705 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002706 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002707 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002708 else if (strcmp(args[myidx], "peers") == 0) {
2709 myidx++;
2710 if (!*(args[myidx])) {
2711 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2712 file, linenum, args[myidx-1]);
2713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
2715 }
2716 curproxy->table.peers.name = strdup(args[myidx++]);
2717 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002718 else if (strcmp(args[myidx], "expire") == 0) {
2719 myidx++;
2720 if (!*(args[myidx])) {
2721 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2722 file, linenum, args[myidx-1]);
2723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
2725 }
2726 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2727 if (err) {
2728 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2729 file, linenum, *err, args[myidx-1]);
2730 err_code |= ERR_ALERT | ERR_FATAL;
2731 goto out;
2732 }
2733 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002734 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002735 }
2736 else if (strcmp(args[myidx], "nopurge") == 0) {
2737 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002738 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002739 }
2740 else if (strcmp(args[myidx], "type") == 0) {
2741 myidx++;
2742 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2743 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2744 file, linenum, args[myidx]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002748 /* myidx already points to next arg */
2749 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002750 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002751 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002752 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002753
2754 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002755 nw = args[myidx];
2756 while (*nw) {
2757 /* the "store" keyword supports a comma-separated list */
2758 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002759 sa = NULL; /* store arg */
2760 while (*nw && *nw != ',') {
2761 if (*nw == '(') {
2762 *nw = 0;
2763 sa = ++nw;
2764 while (*nw != ')') {
2765 if (!*nw) {
2766 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2767 file, linenum, args[0], cw);
2768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
2770 }
2771 nw++;
2772 }
2773 *nw = '\0';
2774 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002775 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002776 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002777 if (*nw)
2778 *nw++ = '\0';
2779 type = stktable_get_data_type(cw);
2780 if (type < 0) {
2781 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2782 file, linenum, args[0], cw);
2783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
2785 }
Willy Tarreauac782882010-06-20 10:41:54 +02002786
2787 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2788 switch (err) {
2789 case PE_NONE: break;
2790 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002791 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2792 file, linenum, args[0], cw);
2793 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002794 break;
2795
2796 case PE_ARG_MISSING:
2797 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2798 file, linenum, args[0], cw);
2799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
2801
2802 case PE_ARG_NOT_USED:
2803 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2804 file, linenum, args[0], cw);
2805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
2807
2808 default:
2809 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2810 file, linenum, args[0], cw);
2811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002813 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002814 }
2815 myidx++;
2816 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002817 else {
2818 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2819 file, linenum, args[myidx]);
2820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002822 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002823 }
2824
2825 if (!curproxy->table.size) {
2826 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2827 file, linenum);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830 }
2831
2832 if (curproxy->table.type == (unsigned int)-1) {
2833 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2834 file, linenum);
2835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
2837 }
2838 }
2839 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002840 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002841 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002842 int myidx = 0;
2843 const char *name = NULL;
2844 int flags;
2845
2846 if (curproxy == &defproxy) {
2847 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
2851
2852 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2853 err_code |= ERR_WARN;
2854 goto out;
2855 }
2856
2857 myidx++;
2858 if ((strcmp(args[myidx], "store") == 0) ||
2859 (strcmp(args[myidx], "store-request") == 0)) {
2860 myidx++;
2861 flags = STK_IS_STORE;
2862 }
2863 else if (strcmp(args[myidx], "store-response") == 0) {
2864 myidx++;
2865 flags = STK_IS_STORE | STK_ON_RSP;
2866 }
2867 else if (strcmp(args[myidx], "match") == 0) {
2868 myidx++;
2869 flags = STK_IS_MATCH;
2870 }
2871 else if (strcmp(args[myidx], "on") == 0) {
2872 myidx++;
2873 flags = STK_IS_MATCH | STK_IS_STORE;
2874 }
2875 else {
2876 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
2879 }
2880
2881 if (*(args[myidx]) == 0) {
2882 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
2885 }
2886
David du Colombier7af46052012-05-16 14:16:48 +02002887 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002888 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002889 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892 }
2893
2894 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002895 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002896 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2897 file, linenum, args[0], expr->fetch->kw);
2898 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002899 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002900 goto out;
2901 }
2902 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002903 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002904 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2905 file, linenum, args[0], expr->fetch->kw);
2906 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002907 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002908 goto out;
2909 }
2910 }
2911
2912 if (strcmp(args[myidx], "table") == 0) {
2913 myidx++;
2914 name = args[myidx++];
2915 }
2916
Willy Tarreauef6494c2010-01-28 17:12:36 +01002917 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002918 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
2919 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
2920 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002921 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002922 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002923 goto out;
2924 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002925 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002926 else if (*(args[myidx])) {
2927 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2928 file, linenum, args[0], args[myidx]);
2929 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002930 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002931 goto out;
2932 }
Emeric Brun97679e72010-09-23 17:56:44 +02002933 if (flags & STK_ON_RSP)
2934 err_code |= warnif_cond_requires_req(cond, file, linenum);
2935 else
2936 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002937
Emeric Brunb982a3d2010-01-04 15:45:53 +01002938 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2939 rule->cond = cond;
2940 rule->expr = expr;
2941 rule->flags = flags;
2942 rule->table.name = name ? strdup(name) : NULL;
2943 LIST_INIT(&rule->list);
2944 if (flags & STK_ON_RSP)
2945 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2946 else
2947 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002950 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002951 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002952
Willy Tarreaubaaee002006-06-26 02:48:02 +02002953 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2954 curproxy->uri_auth = NULL; /* we must detach from the default config */
2955
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002956 if (!*args[1]) {
2957 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002958 } else if (!strcmp(args[1], "admin")) {
2959 struct stats_admin_rule *rule;
2960
2961 if (curproxy == &defproxy) {
2962 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
2965 }
2966
2967 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2968 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2969 err_code |= ERR_ALERT | ERR_ABORT;
2970 goto out;
2971 }
2972
2973 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2974 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2975 file, linenum, args[0], args[1]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002979 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2980 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
2981 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02002982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
2984 }
2985
2986 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2987
2988 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2989 rule->cond = cond;
2990 LIST_INIT(&rule->list);
2991 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 } else if (!strcmp(args[1], "uri")) {
2993 if (*(args[2]) == 0) {
2994 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2998 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002999 err_code |= ERR_ALERT | ERR_ABORT;
3000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 }
3002 } else if (!strcmp(args[1], "realm")) {
3003 if (*(args[2]) == 0) {
3004 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003007 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3008 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_ALERT | ERR_ABORT;
3010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003011 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003012 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003013 unsigned interval;
3014
3015 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3016 if (err) {
3017 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3018 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003021 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3022 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_ALERT | ERR_ABORT;
3024 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003025 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003026 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003027 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003028
3029 if (curproxy == &defproxy) {
3030 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
3033 }
3034
3035 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3036 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3037 err_code |= ERR_ALERT | ERR_ABORT;
3038 goto out;
3039 }
3040
Willy Tarreauff011f22011-01-06 17:51:27 +01003041 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3042 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003043 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3044 file, linenum, args[0]);
3045 err_code |= ERR_WARN;
3046 }
3047
Willy Tarreauff011f22011-01-06 17:51:27 +01003048 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003049
Willy Tarreauff011f22011-01-06 17:51:27 +01003050 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003051 err_code |= ERR_ALERT | ERR_ABORT;
3052 goto out;
3053 }
3054
Willy Tarreauff011f22011-01-06 17:51:27 +01003055 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3056 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003057
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 } else if (!strcmp(args[1], "auth")) {
3059 if (*(args[2]) == 0) {
3060 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3064 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003065 err_code |= ERR_ALERT | ERR_ABORT;
3066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 }
3068 } else if (!strcmp(args[1], "scope")) {
3069 if (*(args[2]) == 0) {
3070 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3074 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003075 err_code |= ERR_ALERT | ERR_ABORT;
3076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 }
3078 } else if (!strcmp(args[1], "enable")) {
3079 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3080 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_ABORT;
3082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003084 } else if (!strcmp(args[1], "hide-version")) {
3085 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3086 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003087 err_code |= ERR_ALERT | ERR_ABORT;
3088 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003089 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003090 } else if (!strcmp(args[1], "show-legends")) {
3091 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3092 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3093 err_code |= ERR_ALERT | ERR_ABORT;
3094 goto out;
3095 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003096 } else if (!strcmp(args[1], "show-node")) {
3097
3098 if (*args[2]) {
3099 int i;
3100 char c;
3101
3102 for (i=0; args[2][i]; i++) {
3103 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003104 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3105 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003106 break;
3107 }
3108
3109 if (!i || args[2][i]) {
3110 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3111 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3112 file, linenum, args[0], args[1]);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116 }
3117
3118 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3119 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3120 err_code |= ERR_ALERT | ERR_ABORT;
3121 goto out;
3122 }
3123 } else if (!strcmp(args[1], "show-desc")) {
3124 char *desc = NULL;
3125
3126 if (*args[2]) {
3127 int i, len=0;
3128 char *d;
3129
3130 for(i=2; *args[i]; i++)
3131 len += strlen(args[i])+1;
3132
3133 desc = d = (char *)calloc(1, len);
3134
3135 d += sprintf(d, "%s", args[2]);
3136 for(i=3; *args[i]; i++)
3137 d += sprintf(d, " %s", args[i]);
3138 }
3139
3140 if (!*args[2] && !global.desc)
3141 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3142 file, linenum, args[1]);
3143 else {
3144 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3145 free(desc);
3146 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3147 err_code |= ERR_ALERT | ERR_ABORT;
3148 goto out;
3149 }
3150 free(desc);
3151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003153stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003154 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 +01003155 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 }
3159 }
3160 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003161 int optnum;
3162
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003163 if (*(args[1]) == '\0') {
3164 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3165 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003169
3170 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3171 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003172 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3173 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3174 file, linenum, cfg_opts[optnum].name);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
3177 }
Willy Tarreau93893792009-07-23 13:19:11 +02003178 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3179 err_code |= ERR_WARN;
3180 goto out;
3181 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003182
Willy Tarreau3842f002009-06-14 11:39:52 +02003183 curproxy->no_options &= ~cfg_opts[optnum].val;
3184 curproxy->options &= ~cfg_opts[optnum].val;
3185
3186 switch (kwm) {
3187 case KWM_STD:
3188 curproxy->options |= cfg_opts[optnum].val;
3189 break;
3190 case KWM_NO:
3191 curproxy->no_options |= cfg_opts[optnum].val;
3192 break;
3193 case KWM_DEF: /* already cleared */
3194 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003195 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003196
Willy Tarreau93893792009-07-23 13:19:11 +02003197 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003198 }
3199 }
3200
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003201 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3202 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003203 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3204 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3205 file, linenum, cfg_opts2[optnum].name);
3206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
Willy Tarreau93893792009-07-23 13:19:11 +02003209 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3210 err_code |= ERR_WARN;
3211 goto out;
3212 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003213
Willy Tarreau3842f002009-06-14 11:39:52 +02003214 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3215 curproxy->options2 &= ~cfg_opts2[optnum].val;
3216
3217 switch (kwm) {
3218 case KWM_STD:
3219 curproxy->options2 |= cfg_opts2[optnum].val;
3220 break;
3221 case KWM_NO:
3222 curproxy->no_options2 |= cfg_opts2[optnum].val;
3223 break;
3224 case KWM_DEF: /* already cleared */
3225 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003226 }
Willy Tarreau93893792009-07-23 13:19:11 +02003227 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003228 }
3229 }
3230
Willy Tarreau3842f002009-06-14 11:39:52 +02003231 if (kwm != KWM_STD) {
3232 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003233 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003236 }
3237
Emeric Brun3a058f32009-06-30 18:26:00 +02003238 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003239 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003241 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003242 if (*(args[2]) != '\0') {
3243 if (!strcmp(args[2], "clf")) {
3244 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003245 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003246 } else {
3247 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003248 err_code |= ERR_ALERT | ERR_FATAL;
3249 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003250 }
3251 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003252 if (curproxy->logformat_string != default_http_log_format &&
3253 curproxy->logformat_string != default_tcp_log_format &&
3254 curproxy->logformat_string != clf_http_log_format)
3255 free(curproxy->logformat_string);
3256 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003257 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003258 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003260 if (curproxy->logformat_string != default_http_log_format &&
3261 curproxy->logformat_string != default_tcp_log_format &&
3262 curproxy->logformat_string != clf_http_log_format)
3263 free(curproxy->logformat_string);
3264 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 else if (!strcmp(args[1], "tcpka")) {
3267 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003268 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003269 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003270
3271 if (curproxy->cap & PR_CAP_FE)
3272 curproxy->options |= PR_O_TCP_CLI_KA;
3273 if (curproxy->cap & PR_CAP_BE)
3274 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 }
3276 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003277 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003278 err_code |= ERR_WARN;
3279
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003281 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003282 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003283 curproxy->options2 &= ~PR_O2_CHK_ANY;
3284 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 if (!*args[2]) { /* no argument */
3286 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3287 curproxy->check_len = strlen(DEF_CHECK_REQ);
3288 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003289 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 curproxy->check_req = (char *)malloc(reqlen);
3291 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003292 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003294 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 if (*args[4])
3296 reqlen += strlen(args[4]);
3297 else
3298 reqlen += strlen("HTTP/1.0");
3299
3300 curproxy->check_req = (char *)malloc(reqlen);
3301 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003302 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003304 }
3305 else if (!strcmp(args[1], "ssl-hello-chk")) {
3306 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003309
Willy Tarreaua534fea2008-08-03 12:19:50 +02003310 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003311 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003312 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003313 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 }
Willy Tarreau23677902007-05-08 23:50:35 +02003315 else if (!strcmp(args[1], "smtpchk")) {
3316 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003317 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003318 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003319 curproxy->options2 &= ~PR_O2_CHK_ANY;
3320 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003321
3322 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3323 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3324 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3325 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3326 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3327 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3328 curproxy->check_req = (char *)malloc(reqlen);
3329 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3330 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3331 } else {
3332 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3333 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3334 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3335 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3336 }
3337 }
3338 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003339 else if (!strcmp(args[1], "pgsql-check")) {
3340 /* use PostgreSQL request to check servers' health */
3341 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3342 err_code |= ERR_WARN;
3343
3344 free(curproxy->check_req);
3345 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003346 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003347 curproxy->options2 |= PR_O2_PGSQL_CHK;
3348
3349 if (*(args[2])) {
3350 int cur_arg = 2;
3351
3352 while (*(args[cur_arg])) {
3353 if (strcmp(args[cur_arg], "user") == 0) {
3354 char * packet;
3355 uint32_t packet_len;
3356 uint32_t pv;
3357
3358 /* suboption header - needs additional argument for it */
3359 if (*(args[cur_arg+1]) == 0) {
3360 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3361 file, linenum, args[0], args[1], args[cur_arg]);
3362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
3364 }
3365
3366 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3367 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3368 pv = htonl(0x30000); /* protocol version 3.0 */
3369
3370 packet = (char*) calloc(1, packet_len);
3371
3372 memcpy(packet + 4, &pv, 4);
3373
3374 /* copy "user" */
3375 memcpy(packet + 8, "user", 4);
3376
3377 /* copy username */
3378 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3379
3380 free(curproxy->check_req);
3381 curproxy->check_req = packet;
3382 curproxy->check_len = packet_len;
3383
3384 packet_len = htonl(packet_len);
3385 memcpy(packet, &packet_len, 4);
3386 cur_arg += 2;
3387 } else {
3388 /* unknown suboption - catchall */
3389 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3390 file, linenum, args[0], args[1]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394 } /* end while loop */
3395 }
3396 }
3397
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003398 else if (!strcmp(args[1], "redis-check")) {
3399 /* use REDIS PING request to check servers' health */
3400 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3401 err_code |= ERR_WARN;
3402
3403 free(curproxy->check_req);
3404 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003405 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003406 curproxy->options2 |= PR_O2_REDIS_CHK;
3407
3408 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3409 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3410 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3411 }
3412
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003413 else if (!strcmp(args[1], "mysql-check")) {
3414 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003415 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3416 err_code |= ERR_WARN;
3417
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003418 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003419 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003420 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003421 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003422
3423 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3424 * const char mysql40_client_auth_pkt[] = {
3425 * "\x0e\x00\x00" // packet length
3426 * "\x01" // packet number
3427 * "\x00\x00" // client capabilities
3428 * "\x00\x00\x01" // max packet
3429 * "haproxy\x00" // username (null terminated string)
3430 * "\x00" // filler (always 0x00)
3431 * "\x01\x00\x00" // packet length
3432 * "\x00" // packet number
3433 * "\x01" // COM_QUIT command
3434 * };
3435 */
3436
3437 if (*(args[2])) {
3438 int cur_arg = 2;
3439
3440 while (*(args[cur_arg])) {
3441 if (strcmp(args[cur_arg], "user") == 0) {
3442 char *mysqluser;
3443 int packetlen, reqlen, userlen;
3444
3445 /* suboption header - needs additional argument for it */
3446 if (*(args[cur_arg+1]) == 0) {
3447 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3448 file, linenum, args[0], args[1], args[cur_arg]);
3449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
3451 }
3452 mysqluser = args[cur_arg + 1];
3453 userlen = strlen(mysqluser);
3454 packetlen = userlen + 7;
3455 reqlen = packetlen + 9;
3456
3457 free(curproxy->check_req);
3458 curproxy->check_req = (char *)calloc(1, reqlen);
3459 curproxy->check_len = reqlen;
3460
3461 snprintf(curproxy->check_req, 4, "%c%c%c",
3462 ((unsigned char) packetlen & 0xff),
3463 ((unsigned char) (packetlen >> 8) & 0xff),
3464 ((unsigned char) (packetlen >> 16) & 0xff));
3465
3466 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003467 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003468 curproxy->check_req[8] = 1;
3469 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3470 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3471 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3472 cur_arg += 2;
3473 } else {
3474 /* unknown suboption - catchall */
3475 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3476 file, linenum, args[0], args[1]);
3477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
3479 }
3480 } /* end while loop */
3481 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003482 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003483 else if (!strcmp(args[1], "ldap-check")) {
3484 /* use LDAP request to check servers' health */
3485 free(curproxy->check_req);
3486 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003487 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003488 curproxy->options2 |= PR_O2_LDAP_CHK;
3489
3490 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3491 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3492 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3493 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003494 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003495 int cur_arg;
3496
3497 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3498 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003499 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003500
Willy Tarreau87cf5142011-08-19 22:57:24 +02003501 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003502
3503 free(curproxy->fwdfor_hdr_name);
3504 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3505 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3506
3507 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3508 cur_arg = 2;
3509 while (*(args[cur_arg])) {
3510 if (!strcmp(args[cur_arg], "except")) {
3511 /* suboption except - needs additional argument for it */
3512 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3513 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3514 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003517 }
3518 /* flush useless bits */
3519 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003520 cur_arg += 2;
3521 } else if (!strcmp(args[cur_arg], "header")) {
3522 /* suboption header - needs additional argument for it */
3523 if (*(args[cur_arg+1]) == 0) {
3524 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3525 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003528 }
3529 free(curproxy->fwdfor_hdr_name);
3530 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3531 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3532 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003533 } else if (!strcmp(args[cur_arg], "if-none")) {
3534 curproxy->options &= ~PR_O_FF_ALWAYS;
3535 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003536 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003537 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003538 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003539 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003542 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003543 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003544 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003545 else if (!strcmp(args[1], "originalto")) {
3546 int cur_arg;
3547
3548 /* insert x-original-to field, but not for the IP address listed as an except.
3549 * set default options (ie: bitfield, header name, etc)
3550 */
3551
3552 curproxy->options |= PR_O_ORGTO;
3553
3554 free(curproxy->orgto_hdr_name);
3555 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3556 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3557
Willy Tarreau87cf5142011-08-19 22:57:24 +02003558 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003559 cur_arg = 2;
3560 while (*(args[cur_arg])) {
3561 if (!strcmp(args[cur_arg], "except")) {
3562 /* suboption except - needs additional argument for it */
3563 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3564 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3565 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003568 }
3569 /* flush useless bits */
3570 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3571 cur_arg += 2;
3572 } else if (!strcmp(args[cur_arg], "header")) {
3573 /* suboption header - needs additional argument for it */
3574 if (*(args[cur_arg+1]) == 0) {
3575 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3576 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003579 }
3580 free(curproxy->orgto_hdr_name);
3581 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3582 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3583 cur_arg += 2;
3584 } else {
3585 /* unknown suboption - catchall */
3586 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3587 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003590 }
3591 } /* end while loop */
3592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 else {
3594 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 }
Willy Tarreau93893792009-07-23 13:19:11 +02003598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003600 else if (!strcmp(args[0], "default_backend")) {
3601 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003603
3604 if (*(args[1]) == 0) {
3605 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003608 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003609 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003610 curproxy->defbe.name = strdup(args[1]);
3611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003613 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003615
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003616 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3617 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 /* enable reconnections to dispatch */
3620 curproxy->options |= PR_O_REDISP;
3621 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003622 else if (!strcmp(args[0], "http-check")) {
3623 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003624 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003625
3626 if (strcmp(args[1], "disable-on-404") == 0) {
3627 /* enable a graceful server shutdown on an HTTP 404 response */
3628 curproxy->options |= PR_O_DISABLE404;
3629 }
Willy Tarreauef781042010-01-27 11:53:01 +01003630 else if (strcmp(args[1], "send-state") == 0) {
3631 /* enable emission of the apparent state of a server in HTTP checks */
3632 curproxy->options2 |= PR_O2_CHK_SNDST;
3633 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003634 else if (strcmp(args[1], "expect") == 0) {
3635 const char *ptr_arg;
3636 int cur_arg;
3637
3638 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3639 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
3642 }
3643
3644 cur_arg = 2;
3645 /* consider exclamation marks, sole or at the beginning of a word */
3646 while (*(ptr_arg = args[cur_arg])) {
3647 while (*ptr_arg == '!') {
3648 curproxy->options2 ^= PR_O2_EXP_INV;
3649 ptr_arg++;
3650 }
3651 if (*ptr_arg)
3652 break;
3653 cur_arg++;
3654 }
3655 /* now ptr_arg points to the beginning of a word past any possible
3656 * exclamation mark, and cur_arg is the argument which holds this word.
3657 */
3658 if (strcmp(ptr_arg, "status") == 0) {
3659 if (!*(args[cur_arg + 1])) {
3660 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3661 file, linenum, args[0], args[1], ptr_arg);
3662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
3664 }
3665 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003666 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003667 curproxy->expect_str = strdup(args[cur_arg + 1]);
3668 }
3669 else if (strcmp(ptr_arg, "string") == 0) {
3670 if (!*(args[cur_arg + 1])) {
3671 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3672 file, linenum, args[0], args[1], ptr_arg);
3673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
3675 }
3676 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003677 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003678 curproxy->expect_str = strdup(args[cur_arg + 1]);
3679 }
3680 else if (strcmp(ptr_arg, "rstatus") == 0) {
3681 if (!*(args[cur_arg + 1])) {
3682 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3683 file, linenum, args[0], args[1], ptr_arg);
3684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
3686 }
3687 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003688 free(curproxy->expect_str);
3689 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3690 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003691 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3692 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3693 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3694 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
3698 }
3699 else if (strcmp(ptr_arg, "rstring") == 0) {
3700 if (!*(args[cur_arg + 1])) {
3701 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3702 file, linenum, args[0], args[1], ptr_arg);
3703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
3705 }
3706 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003707 free(curproxy->expect_str);
3708 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3709 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003710 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3711 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3712 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3713 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
3716 }
3717 }
3718 else {
3719 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3720 file, linenum, args[0], args[1], ptr_arg);
3721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
3723 }
3724 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003725 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003726 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 +02003727 err_code |= ERR_ALERT | ERR_FATAL;
3728 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003729 }
3730 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003731 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003732 if (curproxy == &defproxy) {
3733 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003736 }
3737
Willy Tarreaub80c2302007-11-30 20:51:32 +01003738 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003740
3741 if (strcmp(args[1], "fail") == 0) {
3742 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003743 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003744 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3745 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003748 }
3749
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003750 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3751 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3752 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003755 }
3756 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3757 }
3758 else {
3759 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003762 }
3763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764#ifdef TPROXY
3765 else if (!strcmp(args[0], "transparent")) {
3766 /* enable transparent proxy connections */
3767 curproxy->options |= PR_O_TRANSP;
3768 }
3769#endif
3770 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003771 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003773
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774 if (*(args[1]) == 0) {
3775 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_ALERT | ERR_FATAL;
3777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
3779 curproxy->maxconn = atol(args[1]);
3780 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003781 else if (!strcmp(args[0], "backlog")) { /* backlog */
3782 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003784
3785 if (*(args[1]) == 0) {
3786 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003789 }
3790 curproxy->backlog = atol(args[1]);
3791 }
Willy Tarreau86034312006-12-29 00:10:33 +01003792 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003793 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003795
Willy Tarreau86034312006-12-29 00:10:33 +01003796 if (*(args[1]) == 0) {
3797 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003800 }
3801 curproxy->fullconn = atol(args[1]);
3802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3804 if (*(args[1]) == 0) {
3805 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003809 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3810 if (err) {
3811 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3812 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003815 }
3816 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
3818 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003819 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 if (curproxy == &defproxy) {
3821 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003825 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003827
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 if (strchr(args[1], ':') == NULL) {
3829 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003833 sk = str2sa(args[1]);
3834 if (!sk) {
3835 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
3838 }
3839 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003840 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 }
3842 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003843 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003845
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003846 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3847 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003852 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3854 err_code |= ERR_WARN;
3855
3856 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3857 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3858 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3859 }
3860 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3861 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3862 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3863 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003864 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3865 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3866 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3867 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003868 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003869 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
3872 }
3873 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003874 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003876 char *rport, *raddr;
3877 short realport = 0;
3878 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003880 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003885 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887
3888 if (!*args[2]) {
3889 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3890 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003894
3895 err = invalid_char(args[1]);
3896 if (err) {
3897 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3898 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003901 }
3902
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003903 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003904 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003905
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003906 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3907 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3908 err_code |= ERR_ALERT | ERR_ABORT;
3909 goto out;
3910 }
3911
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003912 /* the servers are linked backwards first */
3913 newsrv->next = curproxy->srv;
3914 curproxy->srv = newsrv;
3915 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02003916 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003917 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003918
Simon Hormanaf514952011-06-21 14:34:57 +09003919 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003920 LIST_INIT(&newsrv->pendconns);
3921 do_check = 0;
3922 newsrv->state = SRV_RUNNING; /* early server setup */
3923 newsrv->last_change = now.tv_sec;
3924 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003926 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003927 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003928 * - IP: => port=+0, relative
3929 * - IP:N => port=N, absolute
3930 * - IP:+N => port=+N, relative
3931 * - IP:-N => port=-N, relative
3932 */
3933 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003934 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003935 if (rport) {
3936 *rport++ = 0;
3937 realport = atol(rport);
3938 if (!isdigit((unsigned char)*rport))
3939 newsrv->state |= SRV_MAPPORTS;
3940 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003941 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003942
Willy Tarreaufab5a432011-03-04 15:31:53 +01003943 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003944 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003945 if (!sk) {
3946 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
3949 }
3950 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02003951 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003952 newsrv->xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02003953
Willy Tarreau173e7fb2012-09-24 22:47:39 +02003954 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02003955 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
3956 file, linenum, newsrv->addr.ss_family, args[2]);
3957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
3959 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003960 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003961
3962 newsrv->check_port = curproxy->defsrv.check_port;
3963 newsrv->inter = curproxy->defsrv.inter;
3964 newsrv->fastinter = curproxy->defsrv.fastinter;
3965 newsrv->downinter = curproxy->defsrv.downinter;
3966 newsrv->rise = curproxy->defsrv.rise;
3967 newsrv->fall = curproxy->defsrv.fall;
3968 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3969 newsrv->minconn = curproxy->defsrv.minconn;
3970 newsrv->maxconn = curproxy->defsrv.maxconn;
3971 newsrv->slowstart = curproxy->defsrv.slowstart;
3972 newsrv->onerror = curproxy->defsrv.onerror;
3973 newsrv->consecutive_errors_limit
3974 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02003975#ifdef OPENSSL
3976 newsrv->use_ssl = curproxy->defsrv.use_ssl;
3977#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003978 newsrv->uweight = newsrv->iweight
3979 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003980
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003981 newsrv->curfd = -1; /* no health-check in progress */
3982 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003984 cur_arg = 3;
3985 } else {
3986 newsrv = &curproxy->defsrv;
3987 cur_arg = 1;
3988 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003989
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003991 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003992 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003993
3994 if (!*args[cur_arg + 1]) {
3995 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3996 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003999 }
4000
4001 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004002 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004003
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004004 if (newsrv->puid <= 0) {
4005 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004006 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004009 }
4010
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004011 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4012 if (node) {
4013 struct server *target = container_of(node, struct server, conf.id);
4014 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4015 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
4018 }
4019 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004020 cur_arg += 2;
4021 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004022 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 newsrv->cookie = strdup(args[cur_arg + 1]);
4024 newsrv->cklen = strlen(args[cur_arg + 1]);
4025 cur_arg += 2;
4026 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004027 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004028 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4029 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4030 cur_arg += 2;
4031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004033 if (!*args[cur_arg + 1]) {
4034 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4035 file, linenum, args[cur_arg]);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
4038 }
4039
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004041 if (newsrv->rise <= 0) {
4042 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4043 file, linenum, args[cur_arg]);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047
Willy Tarreau96839092010-03-29 10:02:24 +02004048 if (newsrv->health)
4049 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 cur_arg += 2;
4051 }
4052 else if (!strcmp(args[cur_arg], "fall")) {
4053 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004054
4055 if (!*args[cur_arg + 1]) {
4056 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4057 file, linenum, args[cur_arg]);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
4061
4062 if (newsrv->fall <= 0) {
4063 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4064 file, linenum, args[cur_arg]);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
4068
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 cur_arg += 2;
4070 }
4071 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004072 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4073 if (err) {
4074 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4075 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004078 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004079 if (val <= 0) {
4080 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4081 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004084 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004085 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 cur_arg += 2;
4087 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004088 else if (!strcmp(args[cur_arg], "fastinter")) {
4089 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4090 if (err) {
4091 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4092 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004095 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004096 if (val <= 0) {
4097 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4098 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004101 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004102 newsrv->fastinter = val;
4103 cur_arg += 2;
4104 }
4105 else if (!strcmp(args[cur_arg], "downinter")) {
4106 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4107 if (err) {
4108 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4109 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004112 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004113 if (val <= 0) {
4114 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4115 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004118 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004119 newsrv->downinter = val;
4120 cur_arg += 2;
4121 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004122 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004123 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004124 if (!sk) {
4125 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004130 cur_arg += 2;
4131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 else if (!strcmp(args[cur_arg], "port")) {
4133 newsrv->check_port = atol(args[cur_arg + 1]);
4134 cur_arg += 2;
4135 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004136 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 newsrv->state |= SRV_BACKUP;
4138 cur_arg ++;
4139 }
Simon Hormanfa461682011-06-25 09:39:49 +09004140 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4141 newsrv->state |= SRV_NON_STICK;
4142 cur_arg ++;
4143 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004144 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4145 newsrv->state |= SRV_SEND_PROXY;
4146 cur_arg ++;
4147 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 else if (!strcmp(args[cur_arg], "weight")) {
4149 int w;
4150 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004151 if (w < 0 || w > 256) {
4152 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004153 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004157 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 cur_arg += 2;
4159 }
4160 else if (!strcmp(args[cur_arg], "minconn")) {
4161 newsrv->minconn = atol(args[cur_arg + 1]);
4162 cur_arg += 2;
4163 }
4164 else if (!strcmp(args[cur_arg], "maxconn")) {
4165 newsrv->maxconn = atol(args[cur_arg + 1]);
4166 cur_arg += 2;
4167 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004168 else if (!strcmp(args[cur_arg], "maxqueue")) {
4169 newsrv->maxqueue = atol(args[cur_arg + 1]);
4170 cur_arg += 2;
4171 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004172 else if (!strcmp(args[cur_arg], "slowstart")) {
4173 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004174 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004175 if (err) {
4176 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4177 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004180 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004181 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004182 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4183 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004186 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004187 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004188 cur_arg += 2;
4189 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004190 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004191
4192 if (!*args[cur_arg + 1]) {
4193 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4194 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004197 }
4198
4199 newsrv->trackit = strdup(args[cur_arg + 1]);
4200
4201 cur_arg += 2;
4202 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004203 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 global.maxsock++;
4205 do_check = 1;
4206 cur_arg += 1;
4207 }
Willy Tarreau96839092010-03-29 10:02:24 +02004208 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4209 newsrv->state |= SRV_MAINTAIN;
4210 newsrv->state &= ~SRV_RUNNING;
4211 newsrv->health = 0;
4212 cur_arg += 1;
4213 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004214 else if (!strcmp(args[cur_arg], "ssl")) {
4215#ifdef USE_OPENSSL
4216 newsrv->use_ssl = 1;
4217 cur_arg += 1;
4218#else /* USE_OPENSSL */
4219 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4220 file, linenum, args[cur_arg]);
4221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
4223#endif /* USE_OPENSSL */
4224 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004225 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4226#ifdef USE_OPENSSL
4227 if (!*args[cur_arg + 1]) {
4228 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4229 file, linenum, args[0], args[cur_arg]);
4230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
4232 }
4233
4234 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4235
4236 cur_arg += 2;
4237 continue;
4238#else
4239 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4240 file, linenum, args[0], args[cur_arg]);
4241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
4243#endif
4244 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004245 else if (!strcmp(args[cur_arg], "nosslv3")) {
4246#ifdef USE_OPENSSL
4247 newsrv->ssl_ctx.nosslv3 = 1;
4248 cur_arg += 1;
4249#else /* USE_OPENSSL */
4250 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4251 file, linenum, args[cur_arg]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254#endif /* USE_OPENSSL */
4255 }
Emeric Brunc0ff4922012-09-28 19:37:02 +02004256 else if (!strcmp(args[cur_arg], "notlsv10")) {
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004257#ifdef USE_OPENSSL
Emeric Brunc0ff4922012-09-28 19:37:02 +02004258 newsrv->ssl_ctx.notlsv10 = 1;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004259 cur_arg += 1;
4260#else /* USE_OPENSSL */
4261 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4262 file, linenum, args[cur_arg]);
4263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265#endif /* USE_OPENSSL */
4266 }
Emeric Brunc0ff4922012-09-28 19:37:02 +02004267 else if (!strcmp(args[cur_arg], "notlsv11")) {
4268#ifdef USE_OPENSSL
4269 newsrv->ssl_ctx.notlsv11 = 1;
4270 cur_arg += 1;
4271#else /* USE_OPENSSL */
4272 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4273 file, linenum, args[cur_arg]);
4274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
4276#endif /* USE_OPENSSL */
4277 }
4278 else if (!strcmp(args[cur_arg], "notlsv12")) {
4279#ifdef USE_OPENSSL
4280 newsrv->ssl_ctx.notlsv12 = 1;
4281 cur_arg += 1;
4282#else /* USE_OPENSSL */
4283 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4284 file, linenum, args[cur_arg]);
4285 err_code |= ERR_ALERT | ERR_FATAL;
4286 goto out;
4287#endif /* USE_OPENSSL */
4288 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004289 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004290 if (!strcmp(args[cur_arg + 1], "none"))
4291 newsrv->observe = HANA_OBS_NONE;
4292 else if (!strcmp(args[cur_arg + 1], "layer4"))
4293 newsrv->observe = HANA_OBS_LAYER4;
4294 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4295 if (curproxy->mode != PR_MODE_HTTP) {
4296 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4297 file, linenum, args[cur_arg + 1]);
4298 err_code |= ERR_ALERT;
4299 }
4300 newsrv->observe = HANA_OBS_LAYER7;
4301 }
4302 else {
4303 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004304 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004305 file, linenum, args[cur_arg], args[cur_arg + 1]);
4306 err_code |= ERR_ALERT | ERR_FATAL;
4307 goto out;
4308 }
4309
4310 cur_arg += 2;
4311 }
4312 else if (!strcmp(args[cur_arg], "on-error")) {
4313 if (!strcmp(args[cur_arg + 1], "fastinter"))
4314 newsrv->onerror = HANA_ONERR_FASTINTER;
4315 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4316 newsrv->onerror = HANA_ONERR_FAILCHK;
4317 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4318 newsrv->onerror = HANA_ONERR_SUDDTH;
4319 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4320 newsrv->onerror = HANA_ONERR_MARKDWN;
4321 else {
4322 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004323 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004324 file, linenum, args[cur_arg], args[cur_arg + 1]);
4325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
4327 }
4328
4329 cur_arg += 2;
4330 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004331 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4332 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4333 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4334 else {
4335 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4336 file, linenum, args[cur_arg], args[cur_arg + 1]);
4337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
4339 }
4340
4341 cur_arg += 2;
4342 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004343 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4344 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4345 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4346 else {
4347 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4348 file, linenum, args[cur_arg], args[cur_arg + 1]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 }
4352
4353 cur_arg += 2;
4354 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004355 else if (!strcmp(args[cur_arg], "error-limit")) {
4356 if (!*args[cur_arg + 1]) {
4357 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4358 file, linenum, args[cur_arg]);
4359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
4361 }
4362
4363 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4364
4365 if (newsrv->consecutive_errors_limit <= 0) {
4366 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4367 file, linenum, args[cur_arg]);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004371 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004372 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004373 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004374 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004375 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004376
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004378#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004379 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004380 file, linenum, "source", "usesrc");
4381#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004382 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004383 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004384#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 }
4388 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004389 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4390 if (!sk) {
4391 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
4394 }
4395 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004396
4397 if (port_low != port_high) {
4398 int i;
4399 if (port_low <= 0 || port_low > 65535 ||
4400 port_high <= 0 || port_high > 65535 ||
4401 port_low > port_high) {
4402 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4403 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004406 }
4407 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4408 for (i = 0; i < newsrv->sport_range->size; i++)
4409 newsrv->sport_range->ports[i] = port_low + i;
4410 }
4411
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004413 while (*(args[cur_arg])) {
4414 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004415#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4416#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004417 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4418 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4419 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004422 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004423#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004424 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004425 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004426 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004429 }
4430 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004431 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004432 newsrv->state |= SRV_TPROXY_CLI;
4433 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004434 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004435 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004436 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4437 char *name, *end;
4438
4439 name = args[cur_arg+1] + 7;
4440 while (isspace(*name))
4441 name++;
4442
4443 end = name;
4444 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4445 end++;
4446
4447 newsrv->state &= ~SRV_TPROXY_MASK;
4448 newsrv->state |= SRV_TPROXY_DYN;
4449 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4450 newsrv->bind_hdr_len = end - name;
4451 memcpy(newsrv->bind_hdr_name, name, end - name);
4452 newsrv->bind_hdr_name[end-name] = '\0';
4453 newsrv->bind_hdr_occ = -1;
4454
4455 /* now look for an occurrence number */
4456 while (isspace(*end))
4457 end++;
4458 if (*end == ',') {
4459 end++;
4460 name = end;
4461 if (*end == '-')
4462 end++;
4463 while (isdigit(*end))
4464 end++;
4465 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4466 }
4467
4468 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4469 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4470 " occurrences values smaller than %d.\n",
4471 file, linenum, MAX_HDR_HISTORY);
4472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
4474 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004475 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004476 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004477 if (!sk) {
4478 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
4481 }
4482 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004483 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004484 }
4485 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004486#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004487 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004488#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004489 cur_arg += 2;
4490 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004491#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004492 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004493 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004496#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4497 } /* "usesrc" */
4498
4499 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4500#ifdef SO_BINDTODEVICE
4501 if (!*args[cur_arg + 1]) {
4502 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4503 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004506 }
4507 if (newsrv->iface_name)
4508 free(newsrv->iface_name);
4509
4510 newsrv->iface_name = strdup(args[cur_arg + 1]);
4511 newsrv->iface_len = strlen(newsrv->iface_name);
4512 global.last_checks |= LSTCHK_NETADM;
4513#else
4514 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4515 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004518#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004519 cur_arg += 2;
4520 continue;
4521 }
4522 /* this keyword in not an option of "source" */
4523 break;
4524 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004525 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004526 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004527 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4528 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004531 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004533 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004534 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 +01004535 file, linenum, newsrv->id);
4536 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004537 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 +01004538 file, linenum);
4539
Willy Tarreau93893792009-07-23 13:19:11 +02004540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542 }
4543 }
4544
4545 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004546 if (newsrv->trackit) {
4547 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4548 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004549 err_code |= ERR_ALERT | ERR_FATAL;
4550 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004551 }
4552
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004553 /* try to get the port from check_addr if check_port not set */
4554 if (!newsrv->check_port)
4555 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004556
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4558 newsrv->check_port = realport; /* by default */
4559 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004560 /* not yet valid, because no port was set on
4561 * the server either. We'll check if we have
4562 * a known port on the first listener.
4563 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004564 struct listener *l;
4565
4566 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
4567 newsrv->check_port = get_host_port(&l->addr);
4568 if (newsrv->check_port)
4569 break;
4570 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004571 }
4572 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4574 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004575 err_code |= ERR_ALERT | ERR_FATAL;
4576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004577 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004578
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004579 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004580 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004581 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4582 err_code |= ERR_ALERT | ERR_ABORT;
4583 goto out;
4584 }
4585
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004586 /* Allocate buffer for partial check results... */
4587 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4588 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4589 err_code |= ERR_ALERT | ERR_ABORT;
4590 goto out;
4591 }
4592
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004593 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004594 newsrv->state |= SRV_CHECKED;
4595 }
4596
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004597 if (!defsrv) {
4598 if (newsrv->state & SRV_BACKUP)
4599 curproxy->srv_bck++;
4600 else
4601 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004602
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004603 newsrv->prev_state = newsrv->state;
4604 }
William Lallemanda73203e2012-03-12 12:48:57 +01004605 }
4606
4607 else if (strcmp(args[0], "unique-id-format") == 0) {
4608 if (!*(args[1])) {
4609 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
4612 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004613 free(curproxy->uniqueid_format_string);
4614 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004615 }
William Lallemanda73203e2012-03-12 12:48:57 +01004616
4617 else if (strcmp(args[0], "unique-id-header") == 0) {
4618 if (!*(args[1])) {
4619 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4620 err_code |= ERR_ALERT | ERR_FATAL;
4621 goto out;
4622 }
4623 free(curproxy->header_unique_id);
4624 curproxy->header_unique_id = strdup(args[1]);
4625 }
4626
William Lallemand723b73a2012-02-08 16:37:49 +01004627 else if (strcmp(args[0], "log-format") == 0) {
4628 if (!*(args[1])) {
4629 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
4632 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004633
4634 if (curproxy->logformat_string != default_http_log_format &&
4635 curproxy->logformat_string != default_tcp_log_format &&
4636 curproxy->logformat_string != clf_http_log_format)
4637 free(curproxy->logformat_string);
4638 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 }
William Lallemand723b73a2012-02-08 16:37:49 +01004640
William Lallemand0f99e342011-10-12 17:50:54 +02004641 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4642 /* delete previous herited or defined syslog servers */
4643 struct logsrv *back;
4644
4645 if (*(args[1]) != 0) {
4646 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
4649 }
4650
William Lallemand723b73a2012-02-08 16:37:49 +01004651 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4652 LIST_DEL(&tmplogsrv->list);
4653 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004654 }
4655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004656 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004657 struct logsrv *logsrv;
4658
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004660 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004661 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004662 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004663 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004664 LIST_INIT(&node->list);
4665 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 }
4668 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004669
4670 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004671
William Lallemand0f99e342011-10-12 17:50:54 +02004672 logsrv->facility = get_log_facility(args[2]);
4673 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004674 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004675 err_code |= ERR_ALERT | ERR_FATAL;
4676 goto out;
4677
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 }
4679
William Lallemand0f99e342011-10-12 17:50:54 +02004680 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004681 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004682 logsrv->level = get_log_level(args[3]);
4683 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004685 err_code |= ERR_ALERT | ERR_FATAL;
4686 goto out;
4687
Willy Tarreaubaaee002006-06-26 02:48:02 +02004688 }
4689 }
4690
William Lallemand0f99e342011-10-12 17:50:54 +02004691 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004692 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004693 logsrv->minlvl = get_log_level(args[4]);
4694 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004695 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004696 err_code |= ERR_ALERT | ERR_FATAL;
4697 goto out;
4698
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004699 }
4700 }
4701
Robert Tsai81ae1952007-12-05 10:47:29 +01004702 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004703 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004704 if (!sk) {
4705 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004706 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
4709 }
William Lallemand0f99e342011-10-12 17:50:54 +02004710 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004711 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004712 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004713 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004714 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
4717 }
William Lallemand0f99e342011-10-12 17:50:54 +02004718 logsrv->addr = *sk;
4719 if (!get_host_port(&logsrv->addr))
4720 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 }
William Lallemand0f99e342011-10-12 17:50:54 +02004722
4723 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 }
4725 else {
4726 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4727 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004728 err_code |= ERR_ALERT | ERR_FATAL;
4729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004730 }
4731 }
4732 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004733 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004734 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004735
Willy Tarreau977b8e42006-12-29 14:19:17 +01004736 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004737 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004738
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004740 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4741 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004745
4746 /* we must first clear any optional default setting */
4747 curproxy->options &= ~PR_O_TPXY_MASK;
4748 free(curproxy->iface_name);
4749 curproxy->iface_name = NULL;
4750 curproxy->iface_len = 0;
4751
Willy Tarreaud5191e72010-02-09 20:50:45 +01004752 sk = str2sa(args[1]);
4753 if (!sk) {
4754 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
4757 }
4758 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004760
4761 cur_arg = 2;
4762 while (*(args[cur_arg])) {
4763 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004764#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4765#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004766 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4767 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4768 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004771 }
4772#endif
4773 if (!*args[cur_arg + 1]) {
4774 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4775 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004778 }
4779
4780 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004781 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004782 curproxy->options |= PR_O_TPXY_CLI;
4783 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004784 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004785 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004786 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4787 char *name, *end;
4788
4789 name = args[cur_arg+1] + 7;
4790 while (isspace(*name))
4791 name++;
4792
4793 end = name;
4794 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4795 end++;
4796
4797 curproxy->options &= ~PR_O_TPXY_MASK;
4798 curproxy->options |= PR_O_TPXY_DYN;
4799 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4800 curproxy->bind_hdr_len = end - name;
4801 memcpy(curproxy->bind_hdr_name, name, end - name);
4802 curproxy->bind_hdr_name[end-name] = '\0';
4803 curproxy->bind_hdr_occ = -1;
4804
4805 /* now look for an occurrence number */
4806 while (isspace(*end))
4807 end++;
4808 if (*end == ',') {
4809 end++;
4810 name = end;
4811 if (*end == '-')
4812 end++;
4813 while (isdigit(*end))
4814 end++;
4815 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4816 }
4817
4818 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4819 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4820 " occurrences values smaller than %d.\n",
4821 file, linenum, MAX_HDR_HISTORY);
4822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
4824 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004825 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004826 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004827 if (!sk) {
4828 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4829 err_code |= ERR_ALERT | ERR_FATAL;
4830 goto out;
4831 }
4832 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004833 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004834 }
4835 global.last_checks |= LSTCHK_NETADM;
4836#if !defined(CONFIG_HAP_LINUX_TPROXY)
4837 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004838#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004839#else /* no TPROXY support */
4840 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004841 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004844#endif
4845 cur_arg += 2;
4846 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004847 }
4848
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004849 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4850#ifdef SO_BINDTODEVICE
4851 if (!*args[cur_arg + 1]) {
4852 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4853 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004854 err_code |= ERR_ALERT | ERR_FATAL;
4855 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004856 }
4857 if (curproxy->iface_name)
4858 free(curproxy->iface_name);
4859
4860 curproxy->iface_name = strdup(args[cur_arg + 1]);
4861 curproxy->iface_len = strlen(curproxy->iface_name);
4862 global.last_checks |= LSTCHK_NETADM;
4863#else
4864 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4865 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004868#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004869 cur_arg += 2;
4870 continue;
4871 }
4872 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004873 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004874 err_code |= ERR_ALERT | ERR_FATAL;
4875 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004878 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4879 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4880 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004881 err_code |= ERR_ALERT | ERR_FATAL;
4882 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004885 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004886 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4887 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004891
4892 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004893 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004894 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004895 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 }
4898 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004899 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004900 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004901 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004902 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 }
4905 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004906 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004907 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004908 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004909 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 }
4912 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004913 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004914 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004915 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004916 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004918 }
4919 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004920 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004921 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004922 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004923 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004926 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004927 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004928 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004929 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004930 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004931 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004932 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004933 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004934 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004935 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004936 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004938 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004939 }
4940 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004941 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004942 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004943 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004944 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004945 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004948 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4950 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004951 err_code |= ERR_ALERT | ERR_FATAL;
4952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954
4955 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004956 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004957 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004958 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 }
4961 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004962 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004963 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004964 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004965 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
4968 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004969 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004970 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004971 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004972 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
4975 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004976 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004977 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004978 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004979 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
4982 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004983 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004984 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004985 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004986 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004989 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004990 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004991 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004992 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004993 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004994 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004995 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004997 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004998
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 if (curproxy == &defproxy) {
5000 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005004 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005005 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005006
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 if (*(args[1]) == 0) {
5008 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005009 err_code |= ERR_ALERT | ERR_FATAL;
5010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005012
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005013 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005014 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5015 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5016 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
5019 }
5020 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5021 }
5022 else if (*args[2]) {
5023 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5024 file, linenum, args[0], args[2]);
5025 err_code |= ERR_ALERT | ERR_FATAL;
5026 goto out;
5027 }
5028
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005029 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005030 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005031 wl->s = strdup(args[1]);
5032 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005033 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005034 }
5035 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005042
Willy Tarreauade5ec42010-01-28 19:33:49 +01005043 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005044 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005045 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005046 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048 }
5049 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005050 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005051 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005052 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005053 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 }
5056 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005057 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005058 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005059 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005060 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 }
5063 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005064 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005065 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5066 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005069 }
5070
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005072 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005073 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005074 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 }
5077 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005079 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005080 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005081 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 }
5084 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005085 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005086 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005087 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005088 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 }
5091 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005092 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005093
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 if (curproxy == &defproxy) {
5095 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005096 err_code |= ERR_ALERT | ERR_FATAL;
5097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005099 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 if (*(args[1]) == 0) {
5103 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106 }
5107
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005108 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005109 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5110 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5111 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
5114 }
5115 err_code |= warnif_cond_requires_req(cond, file, linenum);
5116 }
5117 else if (*args[2]) {
5118 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5119 file, linenum, args[0], args[2]);
5120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
5122 }
5123
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005124 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005125 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005126 wl->s = strdup(args[1]);
5127 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 }
5129 else if (!strcmp(args[0], "errorloc") ||
5130 !strcmp(args[0], "errorloc302") ||
5131 !strcmp(args[0], "errorloc303")) { /* error location */
5132 int errnum, errlen;
5133 char *err;
5134
Willy Tarreau977b8e42006-12-29 14:19:17 +01005135 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005137
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005139 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
5143
5144 errnum = atol(args[1]);
5145 if (!strcmp(args[0], "errorloc303")) {
5146 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5147 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5148 } else {
5149 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5150 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5151 }
5152
Willy Tarreau0f772532006-12-23 20:51:41 +01005153 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5154 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005155 chunk_destroy(&curproxy->errmsg[rc]);
5156 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005157 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005160
5161 if (rc >= HTTP_ERR_SIZE) {
5162 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5163 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 free(err);
5165 }
5166 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005167 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5168 int errnum, errlen, fd;
5169 char *err;
5170 struct stat stat;
5171
5172 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005173 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005174
5175 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005176 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005179 }
5180
5181 fd = open(args[2], O_RDONLY);
5182 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5183 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5184 file, linenum, args[2], args[1]);
5185 if (fd >= 0)
5186 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005187 err_code |= ERR_ALERT | ERR_FATAL;
5188 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005189 }
5190
Willy Tarreau27a674e2009-08-17 07:23:33 +02005191 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005192 errlen = stat.st_size;
5193 } else {
5194 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005195 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005196 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005197 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005198 }
5199
5200 err = malloc(errlen); /* malloc() must succeed during parsing */
5201 errnum = read(fd, err, errlen);
5202 if (errnum != errlen) {
5203 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5204 file, linenum, args[2], args[1]);
5205 close(fd);
5206 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005209 }
5210 close(fd);
5211
5212 errnum = atol(args[1]);
5213 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5214 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005215 chunk_destroy(&curproxy->errmsg[rc]);
5216 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005217 break;
5218 }
5219 }
5220
5221 if (rc >= HTTP_ERR_SIZE) {
5222 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5223 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005224 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005225 free(err);
5226 }
5227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005229 struct cfg_kw_list *kwl;
5230 int index;
5231
5232 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5233 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5234 if (kwl->kw[index].section != CFG_LISTEN)
5235 continue;
5236 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5237 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005238 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005239 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau28a47d62012-09-18 20:02:48 +02005240 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005241 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005242 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005245 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005246 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005247 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005248 err_code |= ERR_WARN;
5249 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005250 }
Willy Tarreau93893792009-07-23 13:19:11 +02005251 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005252 }
5253 }
5254 }
5255
Willy Tarreau6daf3432008-01-22 16:44:08 +01005256 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005257 err_code |= ERR_ALERT | ERR_FATAL;
5258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 }
Willy Tarreau93893792009-07-23 13:19:11 +02005260 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005261 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005262 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263}
5264
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005265int
5266cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5267{
5268
5269 int err_code = 0;
5270 const char *err;
5271
5272 if (!strcmp(args[0], "userlist")) { /* new userlist */
5273 struct userlist *newul;
5274
5275 if (!*args[1]) {
5276 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5277 file, linenum, args[0]);
5278 err_code |= ERR_ALERT | ERR_FATAL;
5279 goto out;
5280 }
5281
5282 err = invalid_char(args[1]);
5283 if (err) {
5284 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5285 file, linenum, *err, args[0], args[1]);
5286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
5288 }
5289
5290 for (newul = userlist; newul; newul = newul->next)
5291 if (!strcmp(newul->name, args[1])) {
5292 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5293 file, linenum, args[1]);
5294 err_code |= ERR_WARN;
5295 goto out;
5296 }
5297
5298 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5299 if (!newul) {
5300 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5301 err_code |= ERR_ALERT | ERR_ABORT;
5302 goto out;
5303 }
5304
5305 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5306 newul->name = strdup(args[1]);
5307
5308 if (!newul->groupusers | !newul->name) {
5309 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5310 err_code |= ERR_ALERT | ERR_ABORT;
5311 goto out;
5312 }
5313
5314 newul->next = userlist;
5315 userlist = newul;
5316
5317 } else if (!strcmp(args[0], "group")) { /* new group */
5318 int cur_arg, i;
5319 const char *err;
5320
5321 if (!*args[1]) {
5322 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5323 file, linenum, args[0]);
5324 err_code |= ERR_ALERT | ERR_FATAL;
5325 goto out;
5326 }
5327
5328 err = invalid_char(args[1]);
5329 if (err) {
5330 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5331 file, linenum, *err, args[0], args[1]);
5332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
5334 }
5335
5336 for(i = 0; i < userlist->grpcnt; i++)
5337 if (!strcmp(userlist->groups[i], args[1])) {
5338 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5339 file, linenum, args[1], userlist->name);
5340 err_code |= ERR_ALERT;
5341 goto out;
5342 }
5343
5344 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5345 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5346 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5347 err_code |= ERR_ALERT | ERR_FATAL;
5348 goto out;
5349 }
5350
5351 cur_arg = 2;
5352
5353 while (*args[cur_arg]) {
5354 if (!strcmp(args[cur_arg], "users")) {
5355 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5356 cur_arg += 2;
5357 continue;
5358 } else {
5359 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5360 file, linenum, args[0]);
5361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
5363 }
5364 }
5365
5366 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5367 } else if (!strcmp(args[0], "user")) { /* new user */
5368 struct auth_users *newuser;
5369 int cur_arg;
5370
5371 if (!*args[1]) {
5372 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5373 file, linenum, args[0]);
5374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
5376 }
5377
5378 for (newuser = userlist->users; newuser; newuser = newuser->next)
5379 if (!strcmp(newuser->user, args[1])) {
5380 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5381 file, linenum, args[1], userlist->name);
5382 err_code |= ERR_ALERT;
5383 goto out;
5384 }
5385
5386 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5387 if (!newuser) {
5388 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5389 err_code |= ERR_ALERT | ERR_ABORT;
5390 goto out;
5391 }
5392
5393 newuser->user = strdup(args[1]);
5394
5395 newuser->next = userlist->users;
5396 userlist->users = newuser;
5397
5398 cur_arg = 2;
5399
5400 while (*args[cur_arg]) {
5401 if (!strcmp(args[cur_arg], "password")) {
5402#ifndef CONFIG_HAP_CRYPT
5403 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5404 file, linenum);
5405 err_code |= ERR_ALERT;
5406#endif
5407 newuser->pass = strdup(args[cur_arg + 1]);
5408 cur_arg += 2;
5409 continue;
5410 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5411 newuser->pass = strdup(args[cur_arg + 1]);
5412 newuser->flags |= AU_O_INSECURE;
5413 cur_arg += 2;
5414 continue;
5415 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005416 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005417 cur_arg += 2;
5418 continue;
5419 } else {
5420 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5421 file, linenum, args[0]);
5422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
5424 }
5425 }
5426 } else {
5427 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5428 err_code |= ERR_ALERT | ERR_FATAL;
5429 }
5430
5431out:
5432 return err_code;
5433}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005434
5435/*
5436 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005437 * Returns the error code, 0 if OK, or any combination of :
5438 * - ERR_ABORT: must abort ASAP
5439 * - ERR_FATAL: we can continue parsing but not start the service
5440 * - ERR_WARN: a warning has been emitted
5441 * - ERR_ALERT: an alert has been emitted
5442 * Only the two first ones can stop processing, the two others are just
5443 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005444 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005445int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005447 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005448 FILE *f;
5449 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005450 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005451 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005452
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 if ((f=fopen(file,"r")) == NULL)
5454 return -1;
5455
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005456 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005457 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005458 char *end;
5459 char *args[MAX_LINE_ARGS + 1];
5460 char *line = thisline;
5461
Willy Tarreaubaaee002006-06-26 02:48:02 +02005462 linenum++;
5463
5464 end = line + strlen(line);
5465
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005466 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5467 /* Check if we reached the limit and the last char is not \n.
5468 * Watch out for the last line without the terminating '\n'!
5469 */
5470 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005471 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005472 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005473 }
5474
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005476 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477 line++;
5478
5479 arg = 0;
5480 args[arg] = line;
5481
5482 while (*line && arg < MAX_LINE_ARGS) {
5483 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5484 * C equivalent value. Other combinations left unchanged (eg: \1).
5485 */
5486 if (*line == '\\') {
5487 int skip = 0;
5488 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5489 *line = line[1];
5490 skip = 1;
5491 }
5492 else if (line[1] == 'r') {
5493 *line = '\r';
5494 skip = 1;
5495 }
5496 else if (line[1] == 'n') {
5497 *line = '\n';
5498 skip = 1;
5499 }
5500 else if (line[1] == 't') {
5501 *line = '\t';
5502 skip = 1;
5503 }
5504 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005505 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005506 unsigned char hex1, hex2;
5507 hex1 = toupper(line[2]) - '0';
5508 hex2 = toupper(line[3]) - '0';
5509 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5510 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5511 *line = (hex1<<4) + hex2;
5512 skip = 3;
5513 }
5514 else {
5515 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005516 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 }
5518 }
5519 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005520 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521 end -= skip;
5522 }
5523 line++;
5524 }
5525 else if (*line == '#' || *line == '\n' || *line == '\r') {
5526 /* end of string, end of loop */
5527 *line = 0;
5528 break;
5529 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005530 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005531 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005532 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005533 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005534 line++;
5535 args[++arg] = line;
5536 }
5537 else {
5538 line++;
5539 }
5540 }
5541
5542 /* empty line */
5543 if (!**args)
5544 continue;
5545
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005546 if (*line) {
5547 /* we had to stop due to too many args.
5548 * Let's terminate the string, print the offending part then cut the
5549 * last arg.
5550 */
5551 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5552 line++;
5553 *line = '\0';
5554
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005555 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005556 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005557 err_code |= ERR_ALERT | ERR_FATAL;
5558 args[arg] = line;
5559 }
5560
Willy Tarreau540abe42007-05-02 20:50:16 +02005561 /* zero out remaining args and ensure that at least one entry
5562 * is zeroed out.
5563 */
5564 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005565 args[arg] = line;
5566 }
5567
Willy Tarreau3842f002009-06-14 11:39:52 +02005568 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005569 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005570 char *tmp;
5571
Willy Tarreau3842f002009-06-14 11:39:52 +02005572 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005573 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005574 for (arg=0; *args[arg+1]; arg++)
5575 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005576 *tmp = '\0'; // fix the next arg to \0
5577 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005578 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005579 else if (!strcmp(args[0], "default")) {
5580 kwm = KWM_DEF;
5581 for (arg=0; *args[arg+1]; arg++)
5582 args[arg] = args[arg+1]; // shift args after inversion
5583 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005584
William Lallemand0f99e342011-10-12 17:50:54 +02005585 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5586 strcmp(args[0], "log") != 0) {
5587 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005588 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005589 }
5590
Willy Tarreau977b8e42006-12-29 14:19:17 +01005591 if (!strcmp(args[0], "listen") ||
5592 !strcmp(args[0], "frontend") ||
5593 !strcmp(args[0], "backend") ||
5594 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005595 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005597 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005598 cursection = strdup(args[0]);
5599 }
5600 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005602 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005603 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005604 }
5605 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005606 confsect = CFG_USERLIST;
5607 free(cursection);
5608 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005609 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005610 else if (!strcmp(args[0], "peers")) {
5611 confsect = CFG_PEERS;
5612 free(cursection);
5613 cursection = strdup(args[0]);
5614 }
5615
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 /* else it's a section keyword */
5617
5618 switch (confsect) {
5619 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005620 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 break;
5622 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005623 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005625 case CFG_USERLIST:
5626 err_code |= cfg_parse_users(file, linenum, args, kwm);
5627 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005628 case CFG_PEERS:
5629 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5630 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005631 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005632 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005633 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005635
5636 if (err_code & ERR_ABORT)
5637 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005639 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005640 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005642 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005643}
5644
Willy Tarreaubb925012009-07-23 13:36:36 +02005645/*
5646 * Returns the error code, 0 if OK, or any combination of :
5647 * - ERR_ABORT: must abort ASAP
5648 * - ERR_FATAL: we can continue parsing but not start the service
5649 * - ERR_WARN: a warning has been emitted
5650 * - ERR_ALERT: an alert has been emitted
5651 * Only the two first ones can stop processing, the two others are just
5652 * indicators.
5653 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005654int check_config_validity()
5655{
5656 int cfgerr = 0;
5657 struct proxy *curproxy = NULL;
5658 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005659 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005660 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005661 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005662 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005663
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005664 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 /*
5666 * Now, check for the integrity of all that we have collected.
5667 */
5668
5669 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005670 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005671
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005672 /* first, we will invert the proxy list order */
5673 curproxy = NULL;
5674 while (proxy) {
5675 struct proxy *next;
5676
5677 next = proxy->next;
5678 proxy->next = curproxy;
5679 curproxy = proxy;
5680 if (!next)
5681 break;
5682 proxy = next;
5683 }
5684
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005686 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005687 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005688 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005689 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005690 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005691 unsigned int next_id;
5692
Willy Tarreau050536d2012-10-04 08:47:34 +02005693 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005694 /* proxy ID not set, use automatic numbering with first
5695 * spare entry starting with next_pxid.
5696 */
5697 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5698 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5699 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005700 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005701 next_pxid++;
5702
Willy Tarreau55ea7572007-06-17 19:56:27 +02005703
Willy Tarreaubaaee002006-06-26 02:48:02 +02005704 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005705 /* ensure we don't keep listeners uselessly bound */
5706 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005707 curproxy = curproxy->next;
5708 continue;
5709 }
5710
Willy Tarreauff01a212009-03-15 13:46:16 +01005711 switch (curproxy->mode) {
5712 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005713 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005714 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005715 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5716 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005717 cfgerr++;
5718 }
5719
5720 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005721 Warning("config : servers will be ignored for %s '%s'.\n",
5722 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005723 break;
5724
5725 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005726 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005727 break;
5728
5729 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005730 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005731 break;
5732 }
5733
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005734 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005735 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005736 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005737 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5738 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005739 cfgerr++;
5740 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005742 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005743 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5744 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005745 cfgerr++;
5746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005747#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005748 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005749 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5750 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005751 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005752 }
5753 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005754 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005755 /* If no LB algo is set in a backend, and we're not in
5756 * transparent mode, dispatch mode nor proxy mode, we
5757 * want to use balance roundrobin by default.
5758 */
5759 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5760 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 }
5762 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005763
Willy Tarreau1620ec32011-08-06 17:05:02 +02005764 if (curproxy->options & PR_O_DISPATCH)
5765 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5766 else if (curproxy->options & PR_O_HTTP_PROXY)
5767 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5768 else if (curproxy->options & PR_O_TRANSP)
5769 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005770
Willy Tarreau1620ec32011-08-06 17:05:02 +02005771 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5772 if (curproxy->options & PR_O_DISABLE404) {
5773 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5774 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5775 err_code |= ERR_WARN;
5776 curproxy->options &= ~PR_O_DISABLE404;
5777 }
5778 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5779 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5780 "send-state", proxy_type_str(curproxy), curproxy->id);
5781 err_code |= ERR_WARN;
5782 curproxy->options &= ~PR_O2_CHK_SNDST;
5783 }
Willy Tarreauef781042010-01-27 11:53:01 +01005784 }
5785
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005786 /* if a default backend was specified, let's find it */
5787 if (curproxy->defbe.name) {
5788 struct proxy *target;
5789
Alex Williams96532db2009-11-01 21:27:13 -05005790 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005791 if (!target) {
5792 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5793 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005794 cfgerr++;
5795 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005796 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5797 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005798 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005799 } else {
5800 free(curproxy->defbe.name);
5801 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005802 /* we force the backend to be present on at least all of
5803 * the frontend's processes.
5804 */
5805 target->bind_proc = curproxy->bind_proc ?
5806 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005807
5808 /* Emit a warning if this proxy also has some servers */
5809 if (curproxy->srv) {
5810 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5811 curproxy->id);
5812 err_code |= ERR_WARN;
5813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814 }
5815 }
5816
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005817 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005818 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5819 /* map jump target for ACT_SETBE in req_rep chain */
5820 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005821 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005822 struct proxy *target;
5823
Willy Tarreaua496b602006-12-17 23:15:24 +01005824 if (exp->action != ACT_SETBE)
5825 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005826
Alex Williams96532db2009-11-01 21:27:13 -05005827 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005828 if (!target) {
5829 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5830 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005831 cfgerr++;
5832 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005833 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5834 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005835 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005836 } else {
5837 free((void *)exp->replace);
5838 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005839 /* we force the backend to be present on at least all of
5840 * the frontend's processes.
5841 */
5842 target->bind_proc = curproxy->bind_proc ?
5843 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005844 }
5845 }
5846 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005847
5848 /* find the target proxy for 'use_backend' rules */
5849 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005850 struct proxy *target;
5851
Alex Williams96532db2009-11-01 21:27:13 -05005852 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005853
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005854 if (!target) {
5855 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5856 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005857 cfgerr++;
5858 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005859 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5860 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005861 cfgerr++;
5862 } else {
5863 free((void *)rule->be.name);
5864 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005865 /* we force the backend to be present on at least all of
5866 * the frontend's processes.
5867 */
5868 target->bind_proc = curproxy->bind_proc ?
5869 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005870 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005871 }
5872
5873 /* find the target proxy for 'use_backend' rules */
5874 list_for_each_entry(srule, &curproxy->server_rules, list) {
5875 struct server *target = findserver(curproxy, srule->srv.name);
5876
5877 if (!target) {
5878 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5879 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5880 cfgerr++;
5881 continue;
5882 }
5883 free((void *)srule->srv.name);
5884 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005885 }
5886
Emeric Brunb982a3d2010-01-04 15:45:53 +01005887 /* find the target table for 'stick' rules */
5888 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5889 struct proxy *target;
5890
Emeric Brun1d33b292010-01-04 15:47:17 +01005891 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5892 if (mrule->flags & STK_IS_STORE)
5893 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5894
Emeric Brunb982a3d2010-01-04 15:45:53 +01005895 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005896 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005897 else
5898 target = curproxy;
5899
5900 if (!target) {
5901 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5902 curproxy->id, mrule->table.name);
5903 cfgerr++;
5904 }
5905 else if (target->table.size == 0) {
5906 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5907 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5908 cfgerr++;
5909 }
Willy Tarreau12785782012-04-27 21:37:17 +02005910 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5911 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005912 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5913 cfgerr++;
5914 }
5915 else {
5916 free((void *)mrule->table.name);
5917 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005918 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005919 }
5920 }
5921
5922 /* find the target table for 'store response' rules */
5923 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5924 struct proxy *target;
5925
Emeric Brun1d33b292010-01-04 15:47:17 +01005926 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5927
Emeric Brunb982a3d2010-01-04 15:45:53 +01005928 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005929 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005930 else
5931 target = curproxy;
5932
5933 if (!target) {
5934 Alert("Proxy '%s': unable to find store table '%s'.\n",
5935 curproxy->id, mrule->table.name);
5936 cfgerr++;
5937 }
5938 else if (target->table.size == 0) {
5939 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5940 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5941 cfgerr++;
5942 }
Willy Tarreau12785782012-04-27 21:37:17 +02005943 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5944 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005945 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5946 cfgerr++;
5947 }
5948 else {
5949 free((void *)mrule->table.name);
5950 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005951 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005952 }
5953 }
5954
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005955 /* find the target table for 'tcp-request' layer 4 rules */
5956 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5957 struct proxy *target;
5958
Willy Tarreau56123282010-08-06 19:06:56 +02005959 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005960 continue;
5961
5962 if (trule->act_prm.trk_ctr.table.n)
5963 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5964 else
5965 target = curproxy;
5966
5967 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005968 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5969 curproxy->id, trule->act_prm.trk_ctr.table.n,
5970 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005971 cfgerr++;
5972 }
5973 else if (target->table.size == 0) {
5974 Alert("Proxy '%s': table '%s' used but not configured.\n",
5975 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5976 cfgerr++;
5977 }
5978 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005979 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 +02005980 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5981 cfgerr++;
5982 }
5983 else {
5984 free(trule->act_prm.trk_ctr.table.n);
5985 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005986 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005987 * to pass a list of counters to track and allocate them right here using
5988 * stktable_alloc_data_type().
5989 */
5990 }
5991 }
5992
Willy Tarreaud1f96522010-08-03 19:34:32 +02005993 /* find the target table for 'tcp-request' layer 6 rules */
5994 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5995 struct proxy *target;
5996
Willy Tarreau56123282010-08-06 19:06:56 +02005997 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005998 continue;
5999
6000 if (trule->act_prm.trk_ctr.table.n)
6001 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6002 else
6003 target = curproxy;
6004
6005 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006006 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6007 curproxy->id, trule->act_prm.trk_ctr.table.n,
6008 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006009 cfgerr++;
6010 }
6011 else if (target->table.size == 0) {
6012 Alert("Proxy '%s': table '%s' used but not configured.\n",
6013 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6014 cfgerr++;
6015 }
6016 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006017 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 +02006018 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6019 cfgerr++;
6020 }
6021 else {
6022 free(trule->act_prm.trk_ctr.table.n);
6023 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006024 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006025 * to pass a list of counters to track and allocate them right here using
6026 * stktable_alloc_data_type().
6027 */
6028 }
6029 }
6030
Emeric Brun32da3c42010-09-23 18:39:19 +02006031 if (curproxy->table.peers.name) {
6032 struct peers *curpeers = peers;
6033
6034 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6035 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6036 free((void *)curproxy->table.peers.name);
6037 curproxy->table.peers.p = peers;
6038 break;
6039 }
6040 }
6041
6042 if (!curpeers) {
6043 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6044 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006045 free((void *)curproxy->table.peers.name);
6046 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006047 cfgerr++;
6048 }
6049 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006050 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6051 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006052 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006053 cfgerr++;
6054 }
6055 }
6056
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006057 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006058 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006059 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6060 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6061 "proxy", curproxy->id);
6062 cfgerr++;
6063 goto out_uri_auth_compat;
6064 }
6065
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006066 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006067 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006068 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006069 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006070
Willy Tarreau95fa4692010-02-01 13:05:50 +01006071 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6072 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006073
6074 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006075 uri_auth_compat_req[i++] = "realm";
6076 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6077 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006078
Willy Tarreau95fa4692010-02-01 13:05:50 +01006079 uri_auth_compat_req[i++] = "unless";
6080 uri_auth_compat_req[i++] = "{";
6081 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6082 uri_auth_compat_req[i++] = "}";
6083 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006084
Willy Tarreauff011f22011-01-06 17:51:27 +01006085 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6086 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006087 cfgerr++;
6088 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006089 }
6090
Willy Tarreauff011f22011-01-06 17:51:27 +01006091 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006092
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006093 if (curproxy->uri_auth->auth_realm) {
6094 free(curproxy->uri_auth->auth_realm);
6095 curproxy->uri_auth->auth_realm = NULL;
6096 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006097
6098 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006099 }
6100out_uri_auth_compat:
6101
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006102 cfgerr += acl_find_targets(curproxy);
6103
Willy Tarreau2738a142006-07-08 17:28:09 +02006104 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006105 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006106 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006107 (!curproxy->timeout.connect ||
6108 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006109 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006110 " | While not properly invalid, you will certainly encounter various problems\n"
6111 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006112 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006113 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006114 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006115 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006116
Willy Tarreau1fa31262007-12-03 00:36:16 +01006117 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6118 * We must still support older configurations, so let's find out whether those
6119 * parameters have been set or must be copied from contimeouts.
6120 */
6121 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006122 if (!curproxy->timeout.tarpit ||
6123 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006124 /* tarpit timeout not set. We search in the following order:
6125 * default.tarpit, curr.connect, default.connect.
6126 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006127 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006128 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006129 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006130 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006131 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006132 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006133 }
6134 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006135 (!curproxy->timeout.queue ||
6136 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006137 /* queue timeout not set. We search in the following order:
6138 * default.queue, curr.connect, default.connect.
6139 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006140 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006141 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006142 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006143 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006144 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006145 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006146 }
6147 }
6148
Willy Tarreau1620ec32011-08-06 17:05:02 +02006149 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006150 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6151 curproxy->check_req = (char *)malloc(curproxy->check_len);
6152 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006153 }
6154
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006155 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006156 if (curproxy->nb_req_cap) {
6157 if (curproxy->mode == PR_MODE_HTTP) {
6158 curproxy->req_cap_pool = create_pool("ptrcap",
6159 curproxy->nb_req_cap * sizeof(char *),
6160 MEM_F_SHARED);
6161 } else {
6162 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6163 proxy_type_str(curproxy), curproxy->id);
6164 err_code |= ERR_WARN;
6165 curproxy->to_log &= ~LW_REQHDR;
6166 curproxy->nb_req_cap = 0;
6167 }
6168 }
6169
6170 if (curproxy->nb_rsp_cap) {
6171 if (curproxy->mode == PR_MODE_HTTP) {
6172 curproxy->rsp_cap_pool = create_pool("ptrcap",
6173 curproxy->nb_rsp_cap * sizeof(char *),
6174 MEM_F_SHARED);
6175 } else {
6176 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6177 proxy_type_str(curproxy), curproxy->id);
6178 err_code |= ERR_WARN;
6179 curproxy->to_log &= ~LW_REQHDR;
6180 curproxy->nb_rsp_cap = 0;
6181 }
6182 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006183
Willy Tarreau196729e2012-05-31 19:30:26 +02006184 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006185 if (!(curproxy->cap & PR_CAP_FE)) {
6186 if (curproxy->logformat_string != default_http_log_format &&
6187 curproxy->logformat_string != default_tcp_log_format &&
6188 curproxy->logformat_string != clf_http_log_format)
6189 free(curproxy->logformat_string);
6190 curproxy->logformat_string = NULL;
6191 }
6192
Willy Tarreau196729e2012-05-31 19:30:26 +02006193 if (curproxy->logformat_string)
6194 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6195
6196 if (curproxy->uniqueid_format_string)
6197 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6198
Willy Tarreaubaaee002006-06-26 02:48:02 +02006199 /* first, we will invert the servers list order */
6200 newsrv = NULL;
6201 while (curproxy->srv) {
6202 struct server *next;
6203
6204 next = curproxy->srv->next;
6205 curproxy->srv->next = newsrv;
6206 newsrv = curproxy->srv;
6207 if (!next)
6208 break;
6209 curproxy->srv = next;
6210 }
6211
Willy Tarreaudd701652010-05-25 23:03:02 +02006212 /* assign automatic UIDs to servers which don't have one yet */
6213 next_id = 1;
6214 newsrv = curproxy->srv;
6215 while (newsrv != NULL) {
6216 if (!newsrv->puid) {
6217 /* server ID not set, use automatic numbering with first
6218 * spare entry starting with next_svid.
6219 */
6220 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6221 newsrv->conf.id.key = newsrv->puid = next_id;
6222 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6223 }
6224 next_id++;
6225 newsrv = newsrv->next;
6226 }
6227
Willy Tarreau20697042007-11-15 23:26:18 +01006228 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006229 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006230
Willy Tarreau62c3be22012-01-20 13:12:32 +01006231 /*
6232 * If this server supports a maxconn parameter, it needs a dedicated
6233 * tasks to fill the emptied slots when a connection leaves.
6234 * Also, resolve deferred tracking dependency if needed.
6235 */
6236 newsrv = curproxy->srv;
6237 while (newsrv != NULL) {
6238 if (newsrv->minconn > newsrv->maxconn) {
6239 /* Only 'minconn' was specified, or it was higher than or equal
6240 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6241 * this will avoid further useless expensive computations.
6242 */
6243 newsrv->maxconn = newsrv->minconn;
6244 } else if (newsrv->maxconn && !newsrv->minconn) {
6245 /* minconn was not specified, so we set it to maxconn */
6246 newsrv->minconn = newsrv->maxconn;
6247 }
6248
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006249#ifdef USE_OPENSSL
6250#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6251#define SSL_OP_NO_COMPRESSION 0
6252#endif
6253#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6254#define SSL_MODE_RELEASE_BUFFERS 0
6255#endif
6256#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6257#define SSL_OP_NO_COMPRESSION 0
6258#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +02006259#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
6260#define SSL_OP_NO_TLSv1_1 0
6261#endif
6262#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
6263#define SSL_OP_NO_TLSv1_2 0
6264#endif
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006265 if (newsrv->use_ssl) {
6266 int ssloptions =
6267 SSL_OP_ALL | /* all known workarounds for bugs */
6268 SSL_OP_NO_SSLv2 |
6269 SSL_OP_NO_COMPRESSION;
6270 int sslmode =
6271 SSL_MODE_ENABLE_PARTIAL_WRITE |
6272 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6273 SSL_MODE_RELEASE_BUFFERS;
6274
6275 /* Initiate SSL context for current server */
6276 newsrv->ssl_ctx.reused_sess = NULL;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02006277 newsrv->xprt = &ssl_sock;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006278 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6279 if(!newsrv->ssl_ctx.ctx) {
6280
6281 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6282 proxy_type_str(curproxy), curproxy->id,
6283 newsrv->id);
6284 cfgerr++;
6285 goto next_srv;
6286 }
6287
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006288 if (newsrv->ssl_ctx.nosslv3)
6289 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brunc0ff4922012-09-28 19:37:02 +02006290 if (newsrv->ssl_ctx.notlsv10)
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006291 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02006292 if (newsrv->ssl_ctx.notlsv11)
6293 ssloptions |= SSL_OP_NO_TLSv1_1;
6294 if (newsrv->ssl_ctx.notlsv12)
6295 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006296 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6297 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6298 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6299 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006300 if (newsrv->ssl_ctx.ciphers &&
6301 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6302 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6303 curproxy->id, newsrv->id,
6304 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6305 cfgerr++;
6306 goto next_srv;
6307 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006308 }
6309#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006310 if (newsrv->trackit) {
6311 struct proxy *px;
6312 struct server *srv;
6313 char *pname, *sname;
6314
6315 pname = newsrv->trackit;
6316 sname = strrchr(pname, '/');
6317
6318 if (sname)
6319 *sname++ = '\0';
6320 else {
6321 sname = pname;
6322 pname = NULL;
6323 }
6324
6325 if (pname) {
6326 px = findproxy(pname, PR_CAP_BE);
6327 if (!px) {
6328 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6329 proxy_type_str(curproxy), curproxy->id,
6330 newsrv->id, pname);
6331 cfgerr++;
6332 goto next_srv;
6333 }
6334 } else
6335 px = curproxy;
6336
6337 srv = findserver(px, sname);
6338 if (!srv) {
6339 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6340 proxy_type_str(curproxy), curproxy->id,
6341 newsrv->id, sname);
6342 cfgerr++;
6343 goto next_srv;
6344 }
6345
6346 if (!(srv->state & SRV_CHECKED)) {
6347 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6348 "tracking as it does not have checks enabled.\n",
6349 proxy_type_str(curproxy), curproxy->id,
6350 newsrv->id, px->id, srv->id);
6351 cfgerr++;
6352 goto next_srv;
6353 }
6354
6355 if (curproxy != px &&
6356 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6357 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6358 "tracking: disable-on-404 option inconsistency.\n",
6359 proxy_type_str(curproxy), curproxy->id,
6360 newsrv->id, px->id, srv->id);
6361 cfgerr++;
6362 goto next_srv;
6363 }
6364
6365 /* if the other server is forced disabled, we have to do the same here */
6366 if (srv->state & SRV_MAINTAIN) {
6367 newsrv->state |= SRV_MAINTAIN;
6368 newsrv->state &= ~SRV_RUNNING;
6369 newsrv->health = 0;
6370 }
6371
6372 newsrv->track = srv;
6373 newsrv->tracknext = srv->tracknext;
6374 srv->tracknext = newsrv;
6375
6376 free(newsrv->trackit);
6377 newsrv->trackit = NULL;
6378 }
6379 next_srv:
6380 newsrv = newsrv->next;
6381 }
6382
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006383 /* We have to initialize the server lookup mechanism depending
6384 * on what LB algorithm was choosen.
6385 */
6386
6387 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6388 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6389 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006390 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6391 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6392 init_server_map(curproxy);
6393 } else {
6394 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6395 fwrr_init_server_groups(curproxy);
6396 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006397 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006398
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006399 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006400 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6401 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6402 fwlc_init_server_tree(curproxy);
6403 } else {
6404 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6405 fas_init_server_tree(curproxy);
6406 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006407 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006408
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006409 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006410 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6411 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6412 chash_init_server_tree(curproxy);
6413 } else {
6414 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6415 init_server_map(curproxy);
6416 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006417 break;
6418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419
6420 if (curproxy->options & PR_O_LOGASAP)
6421 curproxy->to_log &= ~LW_BYTES;
6422
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006423 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006424 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006425 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6426 proxy_type_str(curproxy), curproxy->id);
6427 err_code |= ERR_WARN;
6428 }
6429
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006430 if (curproxy->mode != PR_MODE_HTTP) {
6431 int optnum;
6432
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006433 if (curproxy->uri_auth) {
6434 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6435 proxy_type_str(curproxy), curproxy->id);
6436 err_code |= ERR_WARN;
6437 curproxy->uri_auth = NULL;
6438 }
6439
Willy Tarreau87cf5142011-08-19 22:57:24 +02006440 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006441 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6442 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6443 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006444 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006445 }
6446
6447 if (curproxy->options & PR_O_ORGTO) {
6448 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6449 "originalto", proxy_type_str(curproxy), curproxy->id);
6450 err_code |= ERR_WARN;
6451 curproxy->options &= ~PR_O_ORGTO;
6452 }
6453
6454 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6455 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6456 (curproxy->cap & cfg_opts[optnum].cap) &&
6457 (curproxy->options & cfg_opts[optnum].val)) {
6458 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6459 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6460 err_code |= ERR_WARN;
6461 curproxy->options &= ~cfg_opts[optnum].val;
6462 }
6463 }
6464
6465 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6466 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6467 (curproxy->cap & cfg_opts2[optnum].cap) &&
6468 (curproxy->options2 & cfg_opts2[optnum].val)) {
6469 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6470 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6471 err_code |= ERR_WARN;
6472 curproxy->options2 &= ~cfg_opts2[optnum].val;
6473 }
6474 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006475
Willy Tarreauefa5f512010-03-30 20:13:29 +02006476#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006477 if (curproxy->bind_hdr_occ) {
6478 curproxy->bind_hdr_occ = 0;
6479 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6480 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6481 err_code |= ERR_WARN;
6482 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006483#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006484 }
6485
Willy Tarreaubaaee002006-06-26 02:48:02 +02006486 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006487 * ensure that we're not cross-dressing a TCP server into HTTP.
6488 */
6489 newsrv = curproxy->srv;
6490 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006491 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006492 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6493 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006494 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006495 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006496
Willy Tarreau0cec3312011-10-31 13:49:26 +01006497 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6498 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6499 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6500 err_code |= ERR_WARN;
6501 }
6502
Willy Tarreauefa5f512010-03-30 20:13:29 +02006503#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006504 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6505 newsrv->bind_hdr_occ = 0;
6506 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6507 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6508 err_code |= ERR_WARN;
6509 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006510#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006511 newsrv = newsrv->next;
6512 }
6513
Willy Tarreauc1a21672009-08-16 22:37:44 +02006514 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006515 if (!curproxy->accept)
6516 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006517
Willy Tarreauc1a21672009-08-16 22:37:44 +02006518 if (curproxy->tcp_req.inspect_delay ||
6519 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006520 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006521
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006522 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006523 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006524 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006525 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006526
6527 /* both TCP and HTTP must check switching rules */
6528 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6529 }
6530
6531 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006532 if (curproxy->tcp_req.inspect_delay ||
6533 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6534 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6535
Emeric Brun97679e72010-09-23 17:56:44 +02006536 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6537 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6538
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006539 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006540 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006541 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006542 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006543
6544 /* If the backend does requires RDP cookie persistence, we have to
6545 * enable the corresponding analyser.
6546 */
6547 if (curproxy->options2 & PR_O2_RDPC_PRST)
6548 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6549 }
6550
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006551 /* Configure SSL for each bind line.
6552 * Note: if configuration fails at some point, the ->ctx member
6553 * remains NULL so that listeners can later detach.
6554 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006555 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6556 if (!bind_conf->is_ssl)
6557 continue;
6558#ifdef USE_OPENSSL
6559 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006560 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006561 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006562 cfgerr++;
6563 continue;
6564 }
6565
Emeric Brun4b3091e2012-09-24 15:48:52 +02006566 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006567 Alert("Unable to allocate SSL session cache.\n");
6568 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006569 continue;
6570 }
6571
Emeric Brunfc0421f2012-09-07 17:30:07 +02006572 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006573 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006574#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006575 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006576
Willy Tarreaue6b98942007-10-29 01:09:36 +01006577 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006578 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006579 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006580 if (!listener->luid) {
6581 /* listener ID not set, use automatic numbering with first
6582 * spare entry starting with next_luid.
6583 */
6584 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6585 listener->conf.id.key = listener->luid = next_id;
6586 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006587 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006588 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006589
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006590 /* enable separate counters */
6591 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6592 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6593 if (!listener->name) {
6594 sprintf(trash, "sock-%d", listener->luid);
6595 listener->name = strdup(trash);
6596 }
6597 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006598
Willy Tarreaue6b98942007-10-29 01:09:36 +01006599 if (curproxy->options & PR_O_TCP_NOLING)
6600 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006601 if (!listener->maxconn)
6602 listener->maxconn = curproxy->maxconn;
6603 if (!listener->backlog)
6604 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006605 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006606 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006607 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006608 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006609
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006610 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6611 listener->options |= LI_O_TCP_RULES;
6612
Willy Tarreaude3041d2010-05-31 10:56:17 +02006613 if (curproxy->mon_mask.s_addr)
6614 listener->options |= LI_O_CHK_MONNET;
6615
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006616 /* smart accept mode is automatic in HTTP mode */
6617 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006618 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006619 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6620 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006621 }
6622
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006623 /* Release unused SSL configs */
6624 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6625 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006626 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006627#ifdef USE_OPENSSL
6628 ssl_sock_free_all_ctx(bind_conf);
Emeric Brund94b3fe2012-09-20 18:23:56 +02006629 free(bind_conf->cafile);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006630 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006631 free(bind_conf->ecdhe);
Emeric Brund94b3fe2012-09-20 18:23:56 +02006632 free(bind_conf->crlfile);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006633#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006634 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006635
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006636 /* Check multi-process mode compatibility for the current proxy */
6637 if (global.nbproc > 1) {
6638 int nbproc = 0;
6639 if (curproxy->bind_proc) {
6640 int proc;
6641 for (proc = 0; proc < global.nbproc; proc++) {
6642 if (curproxy->bind_proc & (1 << proc)) {
6643 nbproc++;
6644 }
6645 }
6646 } else {
6647 nbproc = global.nbproc;
6648 }
6649 if (curproxy->table.peers.name) {
6650 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6651 curproxy->id);
6652 cfgerr++;
6653 }
6654 if (nbproc > 1) {
6655 if (curproxy->uri_auth) {
6656 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6657 curproxy->id);
6658 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6659 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6660 curproxy->id);
6661 }
6662 }
6663 if (curproxy->appsession_name) {
6664 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6665 curproxy->id);
6666 }
6667 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6668 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6669 curproxy->id);
6670 }
6671 }
6672 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006673
6674 /* create the task associated with the proxy */
6675 curproxy->task = task_new();
6676 if (curproxy->task) {
6677 curproxy->task->context = curproxy;
6678 curproxy->task->process = manage_proxy;
6679 /* no need to queue, it will be done automatically if some
6680 * listener gets limited.
6681 */
6682 curproxy->task->expire = TICK_ETERNITY;
6683 } else {
6684 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6685 curproxy->id);
6686 cfgerr++;
6687 }
6688
Willy Tarreaubaaee002006-06-26 02:48:02 +02006689 curproxy = curproxy->next;
6690 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006691
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006692 /* Check multi-process mode compatibility */
6693 if (global.nbproc > 1) {
6694 if (global.stats_fe) {
6695 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6696 }
6697 }
6698
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006699 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6700 struct auth_users *curuser;
6701 int g;
6702
6703 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6704 unsigned int group_mask = 0;
6705 char *group = NULL;
6706
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006707 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006708 continue;
6709
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006710 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006711
6712 for (g = 0; g < curuserlist->grpcnt; g++)
6713 if (!strcmp(curuserlist->groups[g], group))
6714 break;
6715
6716 if (g == curuserlist->grpcnt) {
6717 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6718 curuserlist->name, group, curuser->user);
6719 err_code |= ERR_ALERT | ERR_FATAL;
6720 goto out;
6721 }
6722
6723 group_mask |= (1 << g);
6724 }
6725
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006726 free(curuser->u.groups);
6727 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006728 }
6729
6730 for (g = 0; g < curuserlist->grpcnt; g++) {
6731 char *user = NULL;
6732
6733 if (!curuserlist->groupusers[g])
6734 continue;
6735
6736 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6737 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6738 if (!strcmp(curuser->user, user))
6739 break;
6740
6741 if (!curuser) {
6742 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6743 curuserlist->name, user, curuserlist->groups[g]);
6744 err_code |= ERR_ALERT | ERR_FATAL;
6745 goto out;
6746 }
6747
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006748 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006749 }
6750
6751 free(curuserlist->groupusers[g]);
6752 }
6753
6754 free(curuserlist->groupusers);
6755
6756#ifdef DEBUG_AUTH
6757 for (g = 0; g < curuserlist->grpcnt; g++) {
6758 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6759
6760 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006761 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006762 fprintf(stderr, " %s", curuser->user);
6763 }
6764
6765 fprintf(stderr, "\n");
6766 }
6767#endif
6768
Willy Tarreaufbb78422011-06-05 15:38:35 +02006769 }
6770
6771 /* automatically compute fullconn if not set. We must not do it in the
6772 * loop above because cross-references are not yet fully resolved.
6773 */
6774 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6775 /* If <fullconn> is not set, let's set it to 10% of the sum of
6776 * the possible incoming frontend's maxconns.
6777 */
6778 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6779 struct proxy *fe;
6780 int total = 0;
6781
6782 /* sum up the number of maxconns of frontends which
6783 * reference this backend at least once or which are
6784 * the same one ('listen').
6785 */
6786 for (fe = proxy; fe; fe = fe->next) {
6787 struct switching_rule *rule;
6788 struct hdr_exp *exp;
6789 int found = 0;
6790
6791 if (!(fe->cap & PR_CAP_FE))
6792 continue;
6793
6794 if (fe == curproxy) /* we're on a "listen" instance */
6795 found = 1;
6796
6797 if (fe->defbe.be == curproxy) /* "default_backend" */
6798 found = 1;
6799
6800 /* check if a "use_backend" rule matches */
6801 if (!found) {
6802 list_for_each_entry(rule, &fe->switching_rules, list) {
6803 if (rule->be.backend == curproxy) {
6804 found = 1;
6805 break;
6806 }
6807 }
6808 }
6809
6810 /* check if a "reqsetbe" rule matches */
6811 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6812 if (exp->action == ACT_SETBE &&
6813 (struct proxy *)exp->replace == curproxy) {
6814 found = 1;
6815 break;
6816 }
6817 }
6818
6819 /* now we've checked all possible ways to reference a backend
6820 * from a frontend.
6821 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006822 if (!found)
6823 continue;
6824 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006825 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006826 /* we have the sum of the maxconns in <total>. We only
6827 * keep 10% of that sum to set the default fullconn, with
6828 * a hard minimum of 1 (to avoid a divide by zero).
6829 */
6830 curproxy->fullconn = (total + 9) / 10;
6831 if (!curproxy->fullconn)
6832 curproxy->fullconn = 1;
6833 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006834 }
6835
Willy Tarreau056f5682010-06-06 15:51:11 +02006836 /* initialize stick-tables on backend capable proxies. This must not
6837 * be done earlier because the data size may be discovered while parsing
6838 * other proxies.
6839 */
6840 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006841 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006842
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006843 /*
6844 * Recount currently required checks.
6845 */
6846
6847 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6848 int optnum;
6849
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006850 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6851 if (curproxy->options & cfg_opts[optnum].val)
6852 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006853
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006854 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6855 if (curproxy->options2 & cfg_opts2[optnum].val)
6856 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006857 }
6858
Willy Tarreau122541c2011-09-07 21:24:49 +02006859 if (peers) {
6860 struct peers *curpeers = peers, **last;
6861 struct peer *p, *pb;
6862
6863 /* Remove all peers sections which don't have a valid listener.
6864 * This can happen when a peers section is never referenced and
6865 * does not contain a local peer.
6866 */
6867 last = &peers;
6868 while (*last) {
6869 curpeers = *last;
6870 if (curpeers->peers_fe) {
6871 last = &curpeers->next;
6872 continue;
6873 }
6874
6875 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6876 curpeers->id, localpeer);
6877
6878 p = curpeers->remote;
6879 while (p) {
6880 pb = p->next;
6881 free(p->id);
6882 free(p);
6883 p = pb;
6884 }
6885
6886 /* Destroy and unlink this curpeers section.
6887 * Note: curpeers is backed up into *last.
6888 */
6889 free(curpeers->id);
6890 curpeers = curpeers->next;
6891 free(*last);
6892 *last = curpeers;
6893 }
6894 }
6895
Willy Tarreauac1932d2011-10-24 19:14:41 +02006896 if (!global.tune.max_http_hdr)
6897 global.tune.max_http_hdr = MAX_HTTP_HDR;
6898
Willy Tarreau34eb6712011-10-24 18:15:04 +02006899 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006900 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006901 MEM_F_SHARED);
6902
Willy Tarreaubb925012009-07-23 13:36:36 +02006903 if (cfgerr > 0)
6904 err_code |= ERR_ALERT | ERR_FATAL;
6905 out:
6906 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006907}
6908
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006909/*
6910 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6911 * parsing sessions.
6912 */
6913void cfg_register_keywords(struct cfg_kw_list *kwl)
6914{
6915 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6916}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006917
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006918/*
6919 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6920 */
6921void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6922{
6923 LIST_DEL(&kwl->list);
6924 LIST_INIT(&kwl->list);
6925}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006926
6927/*
6928 * Local variables:
6929 * c-indent-level: 8
6930 * c-basic-offset: 8
6931 * End:
6932 */