blob: 4e06f7e7149cf7ce59379c94b7e739b1bdfdd7ad [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 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200468 else if (!strcmp(args[0], "ca-base")) {
469#ifdef USE_OPENSSL
470 if (global.ca_base != NULL) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
472 err_code |= ERR_ALERT;
473 goto out;
474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
479 }
480 global.ca_base = strdup(args[1]);
481#else
482 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
483 err_code |= ERR_ALERT | ERR_FATAL;
484 goto out;
485#endif
486 }
487 else if (!strcmp(args[0], "crt-base")) {
488#ifdef USE_OPENSSL
489 if (global.crt_base != NULL) {
490 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
491 err_code |= ERR_ALERT;
492 goto out;
493 }
494 if (*(args[1]) == 0) {
495 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
496 err_code |= ERR_ALERT | ERR_FATAL;
497 goto out;
498 }
499 global.crt_base = strdup(args[1]);
500#else
501 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
504#endif
505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200506 else if (!strcmp(args[0], "daemon")) {
507 global.mode |= MODE_DAEMON;
508 }
509 else if (!strcmp(args[0], "debug")) {
510 global.mode |= MODE_DEBUG;
511 }
512 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100513 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200515 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200517 }
518 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100524 else if (!strcmp(args[0], "nosplice")) {
525 global.tune.options &= ~GTUNE_USE_SPLICE;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "quiet")) {
528 global.mode |= MODE_QUIET;
529 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200530 else if (!strcmp(args[0], "tune.maxpollevents")) {
531 if (global.tune.maxpollevents != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200540 }
541 global.tune.maxpollevents = atol(args[1]);
542 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100543 else if (!strcmp(args[0], "tune.maxaccept")) {
544 if (global.tune.maxaccept != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100553 }
554 global.tune.maxaccept = atol(args[1]);
555 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200556 else if (!strcmp(args[0], "tune.chksize")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.chksize = atol(args[1]);
563 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200564#ifdef USE_OPENSSL
565 else if (!strcmp(args[0], "tune.sslcachesize")) {
566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.sslcachesize = atol(args[1]);
572 }
573#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200574 else if (!strcmp(args[0], "tune.bufsize")) {
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.tune.bufsize = atol(args[1]);
581 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
582 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200583 trashlen = global.tune.bufsize;
584 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200585 }
586 else if (!strcmp(args[0], "tune.maxrewrite")) {
587 if (*(args[1]) == 0) {
588 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
589 err_code |= ERR_ALERT | ERR_FATAL;
590 goto out;
591 }
592 global.tune.maxrewrite = atol(args[1]);
593 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
594 global.tune.maxrewrite = global.tune.bufsize / 2;
595 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100596 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
597 if (global.tune.client_rcvbuf != 0) {
598 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
599 err_code |= ERR_ALERT;
600 goto out;
601 }
602 if (*(args[1]) == 0) {
603 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
604 err_code |= ERR_ALERT | ERR_FATAL;
605 goto out;
606 }
607 global.tune.client_rcvbuf = atol(args[1]);
608 }
609 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
610 if (global.tune.server_rcvbuf != 0) {
611 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
612 err_code |= ERR_ALERT;
613 goto out;
614 }
615 if (*(args[1]) == 0) {
616 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
617 err_code |= ERR_ALERT | ERR_FATAL;
618 goto out;
619 }
620 global.tune.server_rcvbuf = atol(args[1]);
621 }
622 else if (!strcmp(args[0], "tune.sndbuf.client")) {
623 if (global.tune.client_sndbuf != 0) {
624 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
625 err_code |= ERR_ALERT;
626 goto out;
627 }
628 if (*(args[1]) == 0) {
629 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
630 err_code |= ERR_ALERT | ERR_FATAL;
631 goto out;
632 }
633 global.tune.client_sndbuf = atol(args[1]);
634 }
635 else if (!strcmp(args[0], "tune.sndbuf.server")) {
636 if (global.tune.server_sndbuf != 0) {
637 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
638 err_code |= ERR_ALERT;
639 goto out;
640 }
641 if (*(args[1]) == 0) {
642 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
643 err_code |= ERR_ALERT | ERR_FATAL;
644 goto out;
645 }
646 global.tune.server_sndbuf = atol(args[1]);
647 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200648 else if (!strcmp(args[0], "tune.pipesize")) {
649 if (*(args[1]) == 0) {
650 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
651 err_code |= ERR_ALERT | ERR_FATAL;
652 goto out;
653 }
654 global.tune.pipesize = atol(args[1]);
655 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200656 else if (!strcmp(args[0], "tune.http.maxhdr")) {
657 if (*(args[1]) == 0) {
658 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
661 }
662 global.tune.max_http_hdr = atol(args[1]);
663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200664 else if (!strcmp(args[0], "uid")) {
665 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200666 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200667 err_code |= ERR_ALERT;
668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 }
670 if (*(args[1]) == 0) {
671 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 }
675 global.uid = atol(args[1]);
676 }
677 else if (!strcmp(args[0], "gid")) {
678 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200679 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT;
681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683 if (*(args[1]) == 0) {
684 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200685 err_code |= ERR_ALERT | ERR_FATAL;
686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200687 }
688 global.gid = atol(args[1]);
689 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200690 /* user/group name handling */
691 else if (!strcmp(args[0], "user")) {
692 struct passwd *ha_user;
693 if (global.uid != 0) {
694 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT;
696 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200697 }
698 errno = 0;
699 ha_user = getpwnam(args[1]);
700 if (ha_user != NULL) {
701 global.uid = (int)ha_user->pw_uid;
702 }
703 else {
704 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 +0200705 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200706 }
707 }
708 else if (!strcmp(args[0], "group")) {
709 struct group *ha_group;
710 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200711 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200712 err_code |= ERR_ALERT;
713 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200714 }
715 errno = 0;
716 ha_group = getgrnam(args[1]);
717 if (ha_group != NULL) {
718 global.gid = (int)ha_group->gr_gid;
719 }
720 else {
721 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 +0200722 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200723 }
724 }
725 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 else if (!strcmp(args[0], "nbproc")) {
727 if (global.nbproc != 0) {
728 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT;
730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 }
732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 }
737 global.nbproc = atol(args[1]);
738 }
739 else if (!strcmp(args[0], "maxconn")) {
740 if (global.maxconn != 0) {
741 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200742 err_code |= ERR_ALERT;
743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 }
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 global.maxconn = atol(args[1]);
751#ifdef SYSTEM_MAXCONN
752 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
753 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);
754 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200756 }
757#endif /* SYSTEM_MAXCONN */
758 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200759 else if (!strcmp(args[0], "maxsslconn")) {
760#ifdef USE_OPENSSL
761 if (*(args[1]) == 0) {
762 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
765 }
766 global.maxsslconn = atol(args[1]);
767#else
Emeric Brun0914df82012-10-02 18:45:42 +0200768 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200771#endif
772 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200773 else if (!strcmp(args[0], "maxconnrate")) {
774 if (global.cps_lim != 0) {
775 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
776 err_code |= ERR_ALERT;
777 goto out;
778 }
779 if (*(args[1]) == 0) {
780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
781 err_code |= ERR_ALERT | ERR_FATAL;
782 goto out;
783 }
784 global.cps_lim = atol(args[1]);
785 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100786 else if (!strcmp(args[0], "maxpipes")) {
787 if (global.maxpipes != 0) {
788 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200789 err_code |= ERR_ALERT;
790 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100791 }
792 if (*(args[1]) == 0) {
793 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200794 err_code |= ERR_ALERT | ERR_FATAL;
795 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100796 }
797 global.maxpipes = atol(args[1]);
798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 else if (!strcmp(args[0], "ulimit-n")) {
800 if (global.rlimit_nofile != 0) {
801 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200802 err_code |= ERR_ALERT;
803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 }
810 global.rlimit_nofile = atol(args[1]);
811 }
812 else if (!strcmp(args[0], "chroot")) {
813 if (global.chroot != NULL) {
814 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200815 err_code |= ERR_ALERT;
816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 }
818 if (*(args[1]) == 0) {
819 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200820 err_code |= ERR_ALERT | ERR_FATAL;
821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 }
823 global.chroot = strdup(args[1]);
824 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200825 else if (!strcmp(args[0], "description")) {
826 int i, len=0;
827 char *d;
828
829 if (!*args[1]) {
830 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
831 file, linenum, args[0]);
832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
834 }
835
836 for(i=1; *args[i]; i++)
837 len += strlen(args[i])+1;
838
839 if (global.desc)
840 free(global.desc);
841
842 global.desc = d = (char *)calloc(1, len);
843
844 d += sprintf(d, "%s", args[1]);
845 for(i=2; *args[i]; i++)
846 d += sprintf(d, " %s", args[i]);
847 }
848 else if (!strcmp(args[0], "node")) {
849 int i;
850 char c;
851
852 for (i=0; args[1][i]; i++) {
853 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100854 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
855 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200856 break;
857 }
858
859 if (!i || args[1][i]) {
860 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
861 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
862 file, linenum, args[0]);
863 err_code |= ERR_ALERT | ERR_FATAL;
864 goto out;
865 }
866
867 if (global.node)
868 free(global.node);
869
870 global.node = strdup(args[1]);
871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 else if (!strcmp(args[0], "pidfile")) {
873 if (global.pidfile != NULL) {
874 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200875 err_code |= ERR_ALERT;
876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200877 }
878 if (*(args[1]) == 0) {
879 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 }
883 global.pidfile = strdup(args[1]);
884 }
Emeric Bruned760922010-10-22 17:59:25 +0200885 else if (!strcmp(args[0], "unix-bind")) {
886 int cur_arg = 1;
887 while (*(args[cur_arg])) {
888 if (!strcmp(args[cur_arg], "prefix")) {
889 if (global.unix_bind.prefix != NULL) {
890 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
891 err_code |= ERR_ALERT;
892 cur_arg += 2;
893 continue;
894 }
895
896 if (*(args[cur_arg+1]) == 0) {
897 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901 global.unix_bind.prefix = strdup(args[cur_arg+1]);
902 cur_arg += 2;
903 continue;
904 }
905
906 if (!strcmp(args[cur_arg], "mode")) {
907
908 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
909 cur_arg += 2;
910 continue;
911 }
912
913 if (!strcmp(args[cur_arg], "uid")) {
914
915 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
916 cur_arg += 2;
917 continue;
918 }
919
920 if (!strcmp(args[cur_arg], "gid")) {
921
922 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
923 cur_arg += 2;
924 continue;
925 }
926
927 if (!strcmp(args[cur_arg], "user")) {
928 struct passwd *user;
929
930 user = getpwnam(args[cur_arg + 1]);
931 if (!user) {
932 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
933 file, linenum, args[0], args[cur_arg + 1 ]);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937
938 global.unix_bind.ux.uid = user->pw_uid;
939 cur_arg += 2;
940 continue;
941 }
942
943 if (!strcmp(args[cur_arg], "group")) {
944 struct group *group;
945
946 group = getgrnam(args[cur_arg + 1]);
947 if (!group) {
948 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
949 file, linenum, args[0], args[cur_arg + 1 ]);
950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
952 }
953
954 global.unix_bind.ux.gid = group->gr_gid;
955 cur_arg += 2;
956 continue;
957 }
958
Willy Tarreaub48f9582011-09-05 01:17:06 +0200959 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200960 file, linenum, args[0]);
961 err_code |= ERR_ALERT | ERR_FATAL;
962 goto out;
963 }
964 }
William Lallemand0f99e342011-10-12 17:50:54 +0200965 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
966 /* delete previous herited or defined syslog servers */
967 struct logsrv *back;
968 struct logsrv *tmp;
969
970 if (*(args[1]) != 0) {
971 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
972 err_code |= ERR_ALERT | ERR_FATAL;
973 goto out;
974 }
975
976 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
977 LIST_DEL(&tmp->list);
978 free(tmp);
979 }
980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200982 struct logsrv *logsrv;
983
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 if (*(args[1]) == 0 || *(args[2]) == 0) {
985 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200986 err_code |= ERR_ALERT | ERR_FATAL;
987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 }
William Lallemand0f99e342011-10-12 17:50:54 +0200989
990 logsrv = calloc(1, sizeof(struct logsrv));
991
992 logsrv->facility = get_log_facility(args[2]);
993 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200994 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200996 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998
William Lallemand0f99e342011-10-12 17:50:54 +0200999 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001000 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001001 logsrv->level = get_log_level(args[3]);
1002 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001004 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001005 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001006 }
1007 }
1008
William Lallemand0f99e342011-10-12 17:50:54 +02001009 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001010 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001011 logsrv->minlvl = get_log_level(args[4]);
1012 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001013 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001015 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001016 }
1017 }
1018
Robert Tsai81ae1952007-12-05 10:47:29 +01001019 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001020 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001021 if (!sk) {
1022 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001023 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001024 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001025 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001026 goto out;
1027 }
William Lallemand0f99e342011-10-12 17:50:54 +02001028 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001029 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001030 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001031 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001032 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001034 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001035 goto out;
1036 }
William Lallemand0f99e342011-10-12 17:50:54 +02001037 logsrv->addr = *sk;
1038 if (!get_host_port(&logsrv->addr))
1039 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041
William Lallemand0f99e342011-10-12 17:50:54 +02001042 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001043 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001044 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1045 char *name;
1046 int len;
1047
1048 if (global.log_send_hostname != NULL) {
1049 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1050 err_code |= ERR_ALERT;
1051 goto out;
1052 }
1053
1054 if (*(args[1]))
1055 name = args[1];
1056 else
1057 name = hostname;
1058
1059 len = strlen(name);
1060
1061 /* We'll add a space after the name to respect the log format */
1062 free(global.log_send_hostname);
1063 global.log_send_hostname = malloc(len + 2);
1064 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1065 }
Kevinm48936af2010-12-22 16:08:21 +00001066 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1067 if (*(args[1]) == 0) {
1068 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1069 err_code |= ERR_ALERT | ERR_FATAL;
1070 goto out;
1071 }
1072 free(global.log_tag);
1073 global.log_tag = strdup(args[1]);
1074 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001075 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1076 if (global.spread_checks != 0) {
1077 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001078 err_code |= ERR_ALERT;
1079 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001080 }
1081 if (*(args[1]) == 0) {
1082 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001083 err_code |= ERR_ALERT | ERR_FATAL;
1084 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001085 }
1086 global.spread_checks = atol(args[1]);
1087 if (global.spread_checks < 0 || global.spread_checks > 50) {
1088 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001089 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 }
1092 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001093 struct cfg_kw_list *kwl;
1094 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001095 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001096
1097 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1098 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1099 if (kwl->kw[index].section != CFG_GLOBAL)
1100 continue;
1101 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1102 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001103 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001104 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau28a47d62012-09-18 20:02:48 +02001105 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001106 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001107 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001109 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001110 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001111 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001112 err_code |= ERR_WARN;
1113 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001114 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001115 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001116 }
1117 }
1118 }
1119
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001121 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001123
Willy Tarreau058e9072009-07-20 09:30:05 +02001124 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001125 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127}
1128
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001129void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001131 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 defproxy.mode = PR_MODE_TCP;
1133 defproxy.state = PR_STNEW;
1134 defproxy.maxconn = cfg_maxpconn;
1135 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001136
1137 defproxy.defsrv.inter = DEF_CHKINTR;
1138 defproxy.defsrv.fastinter = 0;
1139 defproxy.defsrv.downinter = 0;
1140 defproxy.defsrv.rise = DEF_RISETIME;
1141 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001142 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001143 defproxy.defsrv.maxqueue = 0;
1144 defproxy.defsrv.minconn = 0;
1145 defproxy.defsrv.maxconn = 0;
1146 defproxy.defsrv.slowstart = 0;
1147 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1148 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1149 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150}
1151
Willy Tarreauade5ec42010-01-28 19:33:49 +01001152
1153static int create_cond_regex_rule(const char *file, int line,
1154 struct proxy *px, int dir, int action, int flags,
1155 const char *cmd, const char *reg, const char *repl,
1156 const char **cond_start)
1157{
1158 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001159 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001160 const char *err;
1161 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001162 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001163
1164 if (px == &defproxy) {
1165 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto err;
1168 }
1169
1170 if (*reg == 0) {
1171 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto err;
1174 }
1175
1176 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1177 err_code |= ERR_WARN;
1178
Willy Tarreau5321c422010-01-28 20:35:13 +01001179 if (cond_start &&
1180 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001181 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1182 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1183 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto err;
1186 }
1187 }
1188 else if (cond_start && **cond_start) {
1189 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1190 file, line, cmd, *cond_start);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto err;
1193 }
1194
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001195 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001196 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001197 else
1198 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001199
Willy Tarreauade5ec42010-01-28 19:33:49 +01001200 preg = calloc(1, sizeof(regex_t));
1201 if (!preg) {
1202 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1203 err_code = ERR_ALERT | ERR_FATAL;
1204 goto err;
1205 }
1206
1207 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1208 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1209 err_code = ERR_ALERT | ERR_FATAL;
1210 goto err;
1211 }
1212
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001213 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001214 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001215 if (repl && err) {
1216 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1217 file, line, cmd, *err);
1218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto err;
1220 }
1221
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001222 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001223 err_code |= ERR_WARN;
1224
Willy Tarreauf4068b62012-05-08 17:37:49 +02001225 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001226 return err_code;
1227 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001228 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001229 free(preg);
1230 return err_code;
1231}
1232
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001234 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001235 * Returns the error code, 0 if OK, or any combination of :
1236 * - ERR_ABORT: must abort ASAP
1237 * - ERR_FATAL: we can continue parsing but not start the service
1238 * - ERR_WARN: a warning has been emitted
1239 * - ERR_ALERT: an alert has been emitted
1240 * Only the two first ones can stop processing, the two others are just
1241 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001242 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001243int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1244{
1245 static struct peers *curpeers = NULL;
1246 struct peer *newpeer = NULL;
1247 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001248 struct bind_conf *bind_conf;
1249 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001250 int err_code = 0;
1251
1252 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1253
1254 err = invalid_char(args[1]);
1255 if (err) {
1256 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1257 file, linenum, *err, args[0], args[1]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 }
1260
1261 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1262 /*
1263 * If there are two proxies with the same name only following
1264 * combinations are allowed:
1265 */
1266 if (strcmp(curpeers->id, args[1]) == 0) {
1267 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1268 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1269 err_code |= ERR_WARN;
1270 }
1271 }
1272
1273 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1275 err_code |= ERR_ALERT | ERR_ABORT;
1276 goto out;
1277 }
1278
1279 curpeers->next = peers;
1280 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001281 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001282 curpeers->conf.line = linenum;
1283 curpeers->last_change = now.tv_sec;
1284 curpeers->id = strdup(args[1]);
1285 }
1286 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1287 char *rport, *raddr;
1288 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001289 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001290 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001291
1292 if (!*args[2]) {
1293 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1294 file, linenum, args[0]);
1295 err_code |= ERR_ALERT | ERR_FATAL;
1296 goto out;
1297 }
1298
1299 err = invalid_char(args[1]);
1300 if (err) {
1301 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1302 file, linenum, *err, args[1]);
1303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
1305 }
1306
1307 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1308 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1309 err_code |= ERR_ALERT | ERR_ABORT;
1310 goto out;
1311 }
1312
1313 /* the peers are linked backwards first */
1314 curpeers->count++;
1315 newpeer->next = curpeers->remote;
1316 curpeers->remote = newpeer;
1317 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001318 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001319 newpeer->conf.line = linenum;
1320
1321 newpeer->last_change = now.tv_sec;
1322 newpeer->id = strdup(args[1]);
1323
1324 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001325 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001326 if (rport) {
1327 *rport++ = 0;
1328 realport = atol(rport);
1329 }
1330 if (!realport) {
1331 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1332 err_code |= ERR_ALERT | ERR_FATAL;
1333 goto out;
1334 }
1335
Willy Tarreaufab5a432011-03-04 15:31:53 +01001336 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001337 free(raddr);
1338 if (!sk) {
1339 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1340 err_code |= ERR_ALERT | ERR_FATAL;
1341 goto out;
1342 }
1343 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001344 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001345 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001346 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001347
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001348 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001349 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1350 file, linenum, newpeer->addr.ss_family, args[2]);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
1353 }
1354
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001355 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001356
1357 if (strcmp(newpeer->id, localpeer) == 0) {
1358 /* Current is local peer, it define a frontend */
1359 newpeer->local = 1;
1360
1361 if (!curpeers->peers_fe) {
1362 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1363 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1364 err_code |= ERR_ALERT | ERR_ABORT;
1365 goto out;
1366 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001367
Willy Tarreau237250c2011-07-29 01:49:03 +02001368 init_new_proxy(curpeers->peers_fe);
1369 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001370
1371 curpeers->peers_fe->last_change = now.tv_sec;
1372 curpeers->peers_fe->id = strdup(args[1]);
1373 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001374 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001375 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1376 curpeers->peers_fe->timeout.connect = 5000;
1377 curpeers->peers_fe->accept = peer_accept;
1378 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001379
1380 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1381
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001382 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1383 if (err_msg && *err_msg) {
1384 indent_msg(&err_msg, 2);
1385 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1386 }
1387 else
1388 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1389 file, linenum, args[0], args[1], args[2]);
1390 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001391 err_code |= ERR_FATAL;
1392 goto out;
1393 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001394
1395 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1396 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1397 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1398 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1399 l->accept = session_accept;
1400 l->handler = process_session;
1401 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1402 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1403 global.maxsock += l->maxconn;
1404 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001405 }
1406 }
1407 } /* neither "peer" nor "peers" */
1408 else if (*args[0] != 0) {
1409 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto out;
1412 }
1413
1414out:
1415 return err_code;
1416}
1417
1418
Willy Tarreau3842f002009-06-14 11:39:52 +02001419int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420{
1421 static struct proxy *curproxy = NULL;
1422 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001423 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001424 int rc;
1425 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001426 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001427 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001428 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001429 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001430 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431
Willy Tarreau977b8e42006-12-29 14:19:17 +01001432 if (!strcmp(args[0], "listen"))
1433 rc = PR_CAP_LISTEN;
1434 else if (!strcmp(args[0], "frontend"))
1435 rc = PR_CAP_FE | PR_CAP_RS;
1436 else if (!strcmp(args[0], "backend"))
1437 rc = PR_CAP_BE | PR_CAP_RS;
1438 else if (!strcmp(args[0], "ruleset"))
1439 rc = PR_CAP_RS;
1440 else
1441 rc = PR_CAP_NONE;
1442
1443 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 if (!*args[1]) {
1445 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1446 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1447 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001448 err_code |= ERR_ALERT | ERR_ABORT;
1449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001451
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001452 err = invalid_char(args[1]);
1453 if (err) {
1454 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1455 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001456 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001457 }
1458
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001459 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1460 /*
1461 * If there are two proxies with the same name only following
1462 * combinations are allowed:
1463 *
1464 * listen backend frontend ruleset
1465 * listen - - - -
1466 * backend - - OK -
1467 * frontend - OK - -
1468 * ruleset - - - -
1469 */
1470
1471 if (!strcmp(curproxy->id, args[1]) &&
1472 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1473 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001474 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1475 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1476 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001477 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001478 }
1479 }
1480
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1482 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001483 err_code |= ERR_ALERT | ERR_ABORT;
1484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001486
Willy Tarreau97cb7802010-01-03 20:23:58 +01001487 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488 curproxy->next = proxy;
1489 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001490 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001491 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001492 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495
1496 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001498 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001499 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001500
Willy Tarreau4348fad2012-09-20 16:48:07 +02001501 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1502
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001503 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1504 if (err_msg && *err_msg) {
1505 indent_msg(&err_msg, 2);
1506 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1507 }
1508 else
1509 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1510 file, linenum, args[0], args[1], args[2]);
1511 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001512 err_code |= ERR_FATAL;
1513 goto out;
1514 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001515
Willy Tarreau4348fad2012-09-20 16:48:07 +02001516 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001517 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519 }
1520
1521 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001522 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001523 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001524
Willy Tarreaubaaee002006-06-26 02:48:02 +02001525 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001527 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001528 curproxy->no_options = defproxy.no_options;
1529 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001530 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001531 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001532 curproxy->except_net = defproxy.except_net;
1533 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001534 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001535 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001536
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001537 if (defproxy.fwdfor_hdr_len) {
1538 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1539 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1540 }
1541
Willy Tarreaub86db342009-11-30 11:50:16 +01001542 if (defproxy.orgto_hdr_len) {
1543 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1544 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1545 }
1546
Mark Lamourinec2247f02012-01-04 13:02:01 -05001547 if (defproxy.server_id_hdr_len) {
1548 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1549 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1550 }
1551
Willy Tarreau977b8e42006-12-29 14:19:17 +01001552 if (curproxy->cap & PR_CAP_FE) {
1553 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001554 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001555 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001556
1557 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001558 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1559 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001560
1561 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563
Willy Tarreau977b8e42006-12-29 14:19:17 +01001564 if (curproxy->cap & PR_CAP_BE) {
1565 curproxy->fullconn = defproxy.fullconn;
1566 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001568 if (defproxy.check_req) {
1569 curproxy->check_req = calloc(1, defproxy.check_len);
1570 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1571 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001572 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001574 if (defproxy.expect_str) {
1575 curproxy->expect_str = strdup(defproxy.expect_str);
1576 if (defproxy.expect_regex) {
1577 /* note: this regex is known to be valid */
1578 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1579 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1580 }
1581 }
1582
Willy Tarreau67402132012-05-31 20:40:20 +02001583 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001584 if (defproxy.cookie_name)
1585 curproxy->cookie_name = strdup(defproxy.cookie_name);
1586 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001587 if (defproxy.cookie_domain)
1588 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001589
Willy Tarreau31936852010-10-06 16:59:56 +02001590 if (defproxy.cookie_maxidle)
1591 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1592
1593 if (defproxy.cookie_maxlife)
1594 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1595
Emeric Brun647caf12009-06-30 17:57:00 +02001596 if (defproxy.rdp_cookie_name)
1597 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1598 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1599
Willy Tarreau01732802007-11-01 22:48:15 +01001600 if (defproxy.url_param_name)
1601 curproxy->url_param_name = strdup(defproxy.url_param_name);
1602 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001603
Benoitaffb4812009-03-25 13:02:10 +01001604 if (defproxy.hh_name)
1605 curproxy->hh_name = strdup(defproxy.hh_name);
1606 curproxy->hh_len = defproxy.hh_len;
1607 curproxy->hh_match_domain = defproxy.hh_match_domain;
1608
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001609 if (defproxy.iface_name)
1610 curproxy->iface_name = strdup(defproxy.iface_name);
1611 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001614 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001615 if (defproxy.capture_name)
1616 curproxy->capture_name = strdup(defproxy.capture_name);
1617 curproxy->capture_namelen = defproxy.capture_namelen;
1618 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001619 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620
Willy Tarreau977b8e42006-12-29 14:19:17 +01001621 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001622 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001623 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001624 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001625 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001626 curproxy->uri_auth = defproxy.uri_auth;
1627 curproxy->mon_net = defproxy.mon_net;
1628 curproxy->mon_mask = defproxy.mon_mask;
1629 if (defproxy.monitor_uri)
1630 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1631 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001632 if (defproxy.defbe.name)
1633 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001634
1635 /* get either a pointer to the logformat string or a copy of it */
1636 curproxy->logformat_string = defproxy.logformat_string;
1637 if (curproxy->logformat_string &&
1638 curproxy->logformat_string != default_http_log_format &&
1639 curproxy->logformat_string != default_tcp_log_format &&
1640 curproxy->logformat_string != clf_http_log_format)
1641 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001642 }
1643
1644 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001645 curproxy->timeout.connect = defproxy.timeout.connect;
1646 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001647 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001648 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001649 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001650 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001651 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001652 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001653 curproxy->source_addr = defproxy.source_addr;
1654 }
1655
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001657
1658 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001659 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001660 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001661 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001662 LIST_INIT(&node->list);
1663 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1664 }
1665
Willy Tarreau196729e2012-05-31 19:30:26 +02001666 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1667 if (curproxy->uniqueid_format_string)
1668 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001669
1670 /* copy default header unique id */
1671 if (defproxy.header_unique_id)
1672 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1673
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001675 curproxy->conf.used_listener_id = EB_ROOT;
1676 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001677
Willy Tarreau93893792009-07-23 13:19:11 +02001678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001679 }
1680 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1681 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001682 /* FIXME-20070101: we should do this too at the end of the
1683 * config parsing to free all default values.
1684 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001685 free(defproxy.check_req);
1686 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001687 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001688 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001689 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001690 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001691 free(defproxy.capture_name);
1692 free(defproxy.monitor_uri);
1693 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001694 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001695 free(defproxy.fwdfor_hdr_name);
1696 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001697 free(defproxy.orgto_hdr_name);
1698 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001699 free(defproxy.server_id_hdr_name);
1700 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001701 free(defproxy.expect_str);
1702 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001703
Willy Tarreau39b06652012-06-01 10:58:06 +02001704 if (defproxy.logformat_string != default_http_log_format &&
1705 defproxy.logformat_string != default_tcp_log_format &&
1706 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001707 free(defproxy.logformat_string);
1708
1709 free(defproxy.uniqueid_format_string);
1710
Willy Tarreaua534fea2008-08-03 12:19:50 +02001711 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001712 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001713
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 /* we cannot free uri_auth because it might already be used */
1715 init_default_instance();
1716 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001717 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 }
1720 else if (curproxy == NULL) {
1721 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001722 err_code |= ERR_ALERT | ERR_FATAL;
1723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 }
1725
Willy Tarreau977b8e42006-12-29 14:19:17 +01001726
1727 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001729 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001730 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001731 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001732
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 if (curproxy == &defproxy) {
1734 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001738 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001739 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001740
Emeric Bruned760922010-10-22 17:59:25 +02001741 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001742 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001743 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001747
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001748 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001749 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001750
1751 /* NOTE: the following line might create several listeners if there
1752 * are comma-separated IPs or port ranges. So all further processing
1753 * will have to be applied to all listeners created after last_listen.
1754 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001755 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1756 if (err_msg && *err_msg) {
1757 indent_msg(&err_msg, 2);
1758 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1759 }
1760 else
1761 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1762 file, linenum, args[0], args[1]);
1763 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001767
Willy Tarreau4348fad2012-09-20 16:48:07 +02001768 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1769 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001770 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001771 }
1772
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001773 cur_arg = 2;
1774 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001775 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001776 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001777 char *err;
1778
Willy Tarreau26982662012-09-12 23:17:10 +02001779 kw = bind_find_kw(args[cur_arg]);
1780 if (kw) {
1781 char *err = NULL;
1782 int code;
1783
1784 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001785 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1786 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001787 cur_arg += 1 + kw->skip ;
1788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
1790 }
1791
Willy Tarreau4348fad2012-09-20 16:48:07 +02001792 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001793 err_code |= code;
1794
1795 if (code) {
1796 if (err && *err) {
1797 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001798 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001799 }
1800 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001801 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1802 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001803 if (code & ERR_FATAL) {
1804 free(err);
1805 cur_arg += 1 + kw->skip;
1806 goto out;
1807 }
1808 }
1809 free(err);
1810 cur_arg += 1 + kw->skip;
1811 continue;
1812 }
1813
Willy Tarreau8638f482012-09-18 18:01:17 +02001814 err = NULL;
1815 if (!bind_dumped) {
1816 bind_dump_kws(&err);
1817 indent_msg(&err, 4);
1818 bind_dumped = 1;
1819 }
1820
1821 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1822 file, linenum, args[0], args[1], args[cur_arg],
1823 err ? " Registered keywords :" : "", err ? err : "");
1824 free(err);
1825
Willy Tarreau93893792009-07-23 13:19:11 +02001826 err_code |= ERR_ALERT | ERR_FATAL;
1827 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001828 }
Willy Tarreau93893792009-07-23 13:19:11 +02001829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830 }
1831 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1832 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1833 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1834 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001835 err_code |= ERR_ALERT | ERR_FATAL;
1836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001837 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001838 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001839 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001840
Willy Tarreaubaaee002006-06-26 02:48:02 +02001841 /* flush useless bits */
1842 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001845 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001846 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001847 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001848
Willy Tarreau1c47f852006-07-09 08:22:27 +02001849 if (!*args[1]) {
1850 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1851 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001852 err_code |= ERR_ALERT | ERR_FATAL;
1853 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001854 }
1855
Willy Tarreaua534fea2008-08-03 12:19:50 +02001856 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001857 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001858 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001859 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001860 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1861
Willy Tarreau93893792009-07-23 13:19:11 +02001862 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1865 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1866 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1867 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1868 else {
1869 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872 }
1873 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001874 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001875 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001876
1877 if (curproxy == &defproxy) {
1878 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1879 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001882 }
1883
1884 if (!*args[1]) {
1885 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1886 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001889 }
1890
1891 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001892 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001893
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001894 if (curproxy->uuid <= 0) {
1895 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001896 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001899 }
1900
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001901 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1902 if (node) {
1903 struct proxy *target = container_of(node, struct proxy, conf.id);
1904 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1905 file, linenum, proxy_type_str(curproxy), curproxy->id,
1906 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1907 err_code |= ERR_ALERT | ERR_FATAL;
1908 goto out;
1909 }
1910 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001911 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001912 else if (!strcmp(args[0], "description")) {
1913 int i, len=0;
1914 char *d;
1915
Cyril Bonté99ed3272010-01-24 23:29:44 +01001916 if (curproxy == &defproxy) {
1917 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1918 file, linenum, args[0]);
1919 err_code |= ERR_ALERT | ERR_FATAL;
1920 goto out;
1921 }
1922
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001923 if (!*args[1]) {
1924 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1925 file, linenum, args[0]);
1926 return -1;
1927 }
1928
1929 for(i=1; *args[i]; i++)
1930 len += strlen(args[i])+1;
1931
1932 d = (char *)calloc(1, len);
1933 curproxy->desc = d;
1934
1935 d += sprintf(d, "%s", args[1]);
1936 for(i=2; *args[i]; i++)
1937 d += sprintf(d, " %s", args[i]);
1938
1939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1941 curproxy->state = PR_STSTOPPED;
1942 }
1943 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1944 curproxy->state = PR_STNEW;
1945 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001946 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1947 int cur_arg = 1;
1948 unsigned int set = 0;
1949
1950 while (*args[cur_arg]) {
1951 int u;
1952 if (strcmp(args[cur_arg], "all") == 0) {
1953 set = 0;
1954 break;
1955 }
1956 else if (strcmp(args[cur_arg], "odd") == 0) {
1957 set |= 0x55555555;
1958 }
1959 else if (strcmp(args[cur_arg], "even") == 0) {
1960 set |= 0xAAAAAAAA;
1961 }
1962 else {
1963 u = str2uic(args[cur_arg]);
1964 if (u < 1 || u > 32) {
1965 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_ALERT | ERR_FATAL;
1968 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001969 }
1970 if (u > global.nbproc) {
1971 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1972 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001973 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001974 }
1975 set |= 1 << (u - 1);
1976 }
1977 cur_arg++;
1978 }
1979 curproxy->bind_proc = set;
1980 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001981 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001982 if (curproxy == &defproxy) {
1983 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001986 }
1987
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001988 err = invalid_char(args[1]);
1989 if (err) {
1990 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1991 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001992 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001993 }
1994
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001995 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
1996 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
1997 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02001998 err_code |= ERR_ALERT | ERR_FATAL;
1999 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002000 }
2001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2003 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004
Willy Tarreau977b8e42006-12-29 14:19:17 +01002005 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002006 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002007
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 if (*(args[1]) == 0) {
2009 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2010 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002011 err_code |= ERR_ALERT | ERR_FATAL;
2012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002014
Willy Tarreau67402132012-05-31 20:40:20 +02002015 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002016 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002017 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002018 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002019 curproxy->cookie_name = strdup(args[1]);
2020 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002021
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 cur_arg = 2;
2023 while (*(args[cur_arg])) {
2024 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002025 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026 }
2027 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002028 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002029 }
2030 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002031 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002032 }
2033 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002034 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002035 }
2036 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002037 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002039 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002040 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002042 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002043 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002045 else if (!strcmp(args[cur_arg], "httponly")) {
2046 curproxy->ck_opts |= PR_CK_HTTPONLY;
2047 }
2048 else if (!strcmp(args[cur_arg], "secure")) {
2049 curproxy->ck_opts |= PR_CK_SECURE;
2050 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002051 else if (!strcmp(args[cur_arg], "domain")) {
2052 if (!*args[cur_arg + 1]) {
2053 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2054 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002057 }
2058
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002059 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002060 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002061 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2062 " dots nor does not start with a dot."
2063 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002064 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002065 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002066 }
2067
2068 err = invalid_domainchar(args[cur_arg + 1]);
2069 if (err) {
2070 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2071 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002074 }
2075
Willy Tarreau68a897b2009-12-03 23:28:34 +01002076 if (!curproxy->cookie_domain) {
2077 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2078 } else {
2079 /* one domain was already specified, add another one by
2080 * building the string which will be returned along with
2081 * the cookie.
2082 */
2083 char *new_ptr;
2084 int new_len = strlen(curproxy->cookie_domain) +
2085 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2086 new_ptr = malloc(new_len);
2087 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2088 free(curproxy->cookie_domain);
2089 curproxy->cookie_domain = new_ptr;
2090 }
Willy Tarreau31936852010-10-06 16:59:56 +02002091 cur_arg++;
2092 }
2093 else if (!strcmp(args[cur_arg], "maxidle")) {
2094 unsigned int maxidle;
2095 const char *res;
2096
2097 if (!*args[cur_arg + 1]) {
2098 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2099 file, linenum, args[cur_arg]);
2100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
2102 }
2103
2104 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2105 if (res) {
2106 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2107 file, linenum, *res, args[cur_arg]);
2108 err_code |= ERR_ALERT | ERR_FATAL;
2109 goto out;
2110 }
2111 curproxy->cookie_maxidle = maxidle;
2112 cur_arg++;
2113 }
2114 else if (!strcmp(args[cur_arg], "maxlife")) {
2115 unsigned int maxlife;
2116 const char *res;
2117
2118 if (!*args[cur_arg + 1]) {
2119 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2120 file, linenum, args[cur_arg]);
2121 err_code |= ERR_ALERT | ERR_FATAL;
2122 goto out;
2123 }
2124
2125 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2126 if (res) {
2127 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2128 file, linenum, *res, args[cur_arg]);
2129 err_code |= ERR_ALERT | ERR_FATAL;
2130 goto out;
2131 }
2132 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002133 cur_arg++;
2134 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002135 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002136 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 +02002137 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002138 err_code |= ERR_ALERT | ERR_FATAL;
2139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 }
2141 cur_arg++;
2142 }
Willy Tarreau67402132012-05-31 20:40:20 +02002143 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2145 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002146 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147 }
2148
Willy Tarreau67402132012-05-31 20:40:20 +02002149 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2151 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002152 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002153 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002154
Willy Tarreau67402132012-05-31 20:40:20 +02002155 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002156 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2157 file, linenum);
2158 err_code |= ERR_ALERT | ERR_FATAL;
2159 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002160 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002161 else if (!strcmp(args[0], "persist")) { /* persist */
2162 if (*(args[1]) == 0) {
2163 Alert("parsing [%s:%d] : missing persist method.\n",
2164 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002167 }
2168
2169 if (!strncmp(args[1], "rdp-cookie", 10)) {
2170 curproxy->options2 |= PR_O2_RDPC_PRST;
2171
Emeric Brunb982a3d2010-01-04 15:45:53 +01002172 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002173 const char *beg, *end;
2174
2175 beg = args[1] + 11;
2176 end = strchr(beg, ')');
2177
2178 if (!end || end == beg) {
2179 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2180 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002183 }
2184
2185 free(curproxy->rdp_cookie_name);
2186 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2187 curproxy->rdp_cookie_len = end-beg;
2188 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002189 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002190 free(curproxy->rdp_cookie_name);
2191 curproxy->rdp_cookie_name = strdup("msts");
2192 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2193 }
2194 else { /* syntax */
2195 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2196 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002199 }
2200 }
2201 else {
2202 Alert("parsing [%s:%d] : unknown persist method.\n",
2203 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002206 }
2207 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002208 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002209 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002211 if (curproxy == &defproxy) {
2212 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2213 err_code |= ERR_ALERT | ERR_FATAL;
2214 goto out;
2215 }
2216
Willy Tarreau977b8e42006-12-29 14:19:17 +01002217 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002218 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002219
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002221 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 }
2226 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002227 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 curproxy->appsession_name = strdup(args[1]);
2229 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2230 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002231 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2232 if (err) {
2233 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2234 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002237 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002238 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002239
Willy Tarreau51041c72007-09-09 21:56:53 +02002240 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2241 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_ABORT;
2243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002245
2246 cur_arg = 6;
2247 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002248 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2249 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002250 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002251 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002252 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002253 } else if (!strcmp(args[cur_arg], "prefix")) {
2254 curproxy->options2 |= PR_O2_AS_PFX;
2255 } else if (!strcmp(args[cur_arg], "mode")) {
2256 if (!*args[cur_arg + 1]) {
2257 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2258 file, linenum, args[0], args[cur_arg]);
2259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
2261 }
2262
2263 cur_arg++;
2264 if (!strcmp(args[cur_arg], "query-string")) {
2265 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2266 curproxy->options2 |= PR_O2_AS_M_QS;
2267 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2268 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2269 curproxy->options2 |= PR_O2_AS_M_PP;
2270 } else {
2271 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
2274 }
2275 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002276 cur_arg++;
2277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 } /* Url App Session */
2279 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002280 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002282
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002284 if (curproxy == &defproxy) {
2285 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 if (*(args[4]) == 0) {
2291 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2292 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002296 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 curproxy->capture_name = strdup(args[2]);
2298 curproxy->capture_namelen = strlen(curproxy->capture_name);
2299 curproxy->capture_len = atol(args[4]);
2300 if (curproxy->capture_len >= CAPTURE_LEN) {
2301 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2302 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002303 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 curproxy->capture_len = CAPTURE_LEN - 1;
2305 }
2306 curproxy->to_log |= LW_COOKIE;
2307 }
2308 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2309 struct cap_hdr *hdr;
2310
2311 if (curproxy == &defproxy) {
2312 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 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 }
2316
2317 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2318 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2319 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 }
2323
2324 hdr = calloc(sizeof(struct cap_hdr), 1);
2325 hdr->next = curproxy->req_cap;
2326 hdr->name = strdup(args[3]);
2327 hdr->namelen = strlen(args[3]);
2328 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002329 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 hdr->index = curproxy->nb_req_cap++;
2331 curproxy->req_cap = hdr;
2332 curproxy->to_log |= LW_REQHDR;
2333 }
2334 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2335 struct cap_hdr *hdr;
2336
2337 if (curproxy == &defproxy) {
2338 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 +02002339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 }
2342
2343 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2344 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2345 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002348 }
2349 hdr = calloc(sizeof(struct cap_hdr), 1);
2350 hdr->next = curproxy->rsp_cap;
2351 hdr->name = strdup(args[3]);
2352 hdr->namelen = strlen(args[3]);
2353 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002354 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 hdr->index = curproxy->nb_rsp_cap++;
2356 curproxy->rsp_cap = hdr;
2357 curproxy->to_log |= LW_RSPHDR;
2358 }
2359 else {
2360 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2361 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 }
2365 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002367 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002368 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002369
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 if (*(args[1]) == 0) {
2371 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2372 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 }
2376 curproxy->conn_retries = atol(args[1]);
2377 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002378 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002379 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002380
2381 if (curproxy == &defproxy) {
2382 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
2385 }
2386
Willy Tarreauff011f22011-01-06 17:51:27 +01002387 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 +01002388 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2389 file, linenum, args[0]);
2390 err_code |= ERR_WARN;
2391 }
2392
Willy Tarreauff011f22011-01-06 17:51:27 +01002393 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002394
Willy Tarreauff011f22011-01-06 17:51:27 +01002395 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002396 err_code |= ERR_ALERT | ERR_ABORT;
2397 goto out;
2398 }
2399
Willy Tarreauff011f22011-01-06 17:51:27 +01002400 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2401 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002402 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002403 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2404 /* set the header name and length into the proxy structure */
2405 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2406 err_code |= ERR_WARN;
2407
2408 if (!*args[1]) {
2409 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2410 file, linenum, args[0]);
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
2413 }
2414
2415 /* set the desired header name */
2416 free(curproxy->server_id_hdr_name);
2417 curproxy->server_id_hdr_name = strdup(args[1]);
2418 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2419 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002420 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002421 if (curproxy == &defproxy) {
2422 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002425 }
2426
Willy Tarreauef6494c2010-01-28 17:12:36 +01002427 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002428 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2429 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002432 }
2433
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002434 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2435 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2436 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002439 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002440
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002441 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002442 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002443 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002444 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002445 struct redirect_rule *rule;
2446 int cur_arg;
2447 int type = REDIRECT_TYPE_NONE;
2448 int code = 302;
2449 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002450 char *cookie = NULL;
2451 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002452 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002453
Cyril Bonté99ed3272010-01-24 23:29:44 +01002454 if (curproxy == &defproxy) {
2455 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
2458 }
2459
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002460 cur_arg = 1;
2461 while (*(args[cur_arg])) {
2462 if (!strcmp(args[cur_arg], "location")) {
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 Tarreaub463dfb2008-06-07 23:08:56 +02002468 }
2469
2470 type = REDIRECT_TYPE_LOCATION;
2471 cur_arg++;
2472 destination = args[cur_arg];
2473 }
2474 else if (!strcmp(args[cur_arg], "prefix")) {
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 Tarreaub463dfb2008-06-07 23:08:56 +02002480 }
2481
2482 type = REDIRECT_TYPE_PREFIX;
2483 cur_arg++;
2484 destination = args[cur_arg];
2485 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002486 else if (!strcmp(args[cur_arg], "scheme")) {
2487 if (!*args[cur_arg + 1]) {
2488 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2489 file, linenum, args[0], args[cur_arg]);
2490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
2492 }
2493
2494 type = REDIRECT_TYPE_SCHEME;
2495 cur_arg++;
2496 destination = args[cur_arg];
2497 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002498 else if (!strcmp(args[cur_arg], "set-cookie")) {
2499 if (!*args[cur_arg + 1]) {
2500 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2501 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002504 }
2505
2506 cur_arg++;
2507 cookie = args[cur_arg];
2508 cookie_set = 1;
2509 }
2510 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2511 if (!*args[cur_arg + 1]) {
2512 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2513 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002516 }
2517
2518 cur_arg++;
2519 cookie = args[cur_arg];
2520 cookie_set = 0;
2521 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002522 else if (!strcmp(args[cur_arg],"code")) {
2523 if (!*args[cur_arg + 1]) {
2524 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2525 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002528 }
2529 cur_arg++;
2530 code = atol(args[cur_arg]);
2531 if (code < 301 || code > 303) {
2532 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2533 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002536 }
2537 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002538 else if (!strcmp(args[cur_arg],"drop-query")) {
2539 flags |= REDIRECT_FLAG_DROP_QS;
2540 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002541 else if (!strcmp(args[cur_arg],"append-slash")) {
2542 flags |= REDIRECT_FLAG_APPEND_SLASH;
2543 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002544 else if (strcmp(args[cur_arg], "if") == 0 ||
2545 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002546 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002547 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002548 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2549 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
2552 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002553 break;
2554 }
2555 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002556 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 +02002557 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002560 }
2561 cur_arg++;
2562 }
2563
2564 if (type == REDIRECT_TYPE_NONE) {
2565 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2566 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002569 }
2570
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002571 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2572 rule->cond = cond;
2573 rule->rdr_str = strdup(destination);
2574 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002575 if (cookie) {
2576 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002577 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002578 */
2579 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002580 if (cookie_set) {
2581 rule->cookie_str = malloc(rule->cookie_len + 10);
2582 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2583 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2584 rule->cookie_len += 9;
2585 } else {
2586 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002587 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002588 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2589 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002590 }
2591 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002592 rule->type = type;
2593 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002594 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002595 LIST_INIT(&rule->list);
2596 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002597 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2598 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002599 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002600 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002601 struct switching_rule *rule;
2602
Willy Tarreaub099aca2008-10-12 17:26:37 +02002603 if (curproxy == &defproxy) {
2604 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002607 }
2608
Willy Tarreau55ea7572007-06-17 19:56:27 +02002609 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002610 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002611
2612 if (*(args[1]) == 0) {
2613 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002616 }
2617
Willy Tarreauef6494c2010-01-28 17:12:36 +01002618 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002619 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2620 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002623 }
2624
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002625 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2626 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2627 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002630 }
2631
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002632 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002633
Willy Tarreau55ea7572007-06-17 19:56:27 +02002634 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2635 rule->cond = cond;
2636 rule->be.name = strdup(args[1]);
2637 LIST_INIT(&rule->list);
2638 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2639 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002640 else if (strcmp(args[0], "use-server") == 0) {
2641 struct server_rule *rule;
2642
2643 if (curproxy == &defproxy) {
2644 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
2647 }
2648
2649 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2650 err_code |= ERR_WARN;
2651
2652 if (*(args[1]) == 0) {
2653 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
2656 }
2657
2658 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2659 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 + 2, &errmsg)) == NULL) {
2666 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2667 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
2670 }
2671
2672 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2673
2674 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2675 rule->cond = cond;
2676 rule->srv.name = strdup(args[1]);
2677 LIST_INIT(&rule->list);
2678 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2679 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2680 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002681 else if ((!strcmp(args[0], "force-persist")) ||
2682 (!strcmp(args[0], "ignore-persist"))) {
2683 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002684
2685 if (curproxy == &defproxy) {
2686 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2687 err_code |= ERR_ALERT | ERR_FATAL;
2688 goto out;
2689 }
2690
2691 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2692 err_code |= ERR_WARN;
2693
Willy Tarreauef6494c2010-01-28 17:12:36 +01002694 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002695 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2696 file, linenum, args[0]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002701 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2702 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2703 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
2706 }
2707
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002708 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002709
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002710 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002711 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002712 if (!strcmp(args[0], "force-persist")) {
2713 rule->type = PERSIST_TYPE_FORCE;
2714 } else {
2715 rule->type = PERSIST_TYPE_IGNORE;
2716 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002717 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002718 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002719 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002720 else if (!strcmp(args[0], "stick-table")) {
2721 int myidx = 1;
2722
Emeric Brun32da3c42010-09-23 18:39:19 +02002723 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002724 curproxy->table.type = (unsigned int)-1;
2725 while (*args[myidx]) {
2726 const char *err;
2727
2728 if (strcmp(args[myidx], "size") == 0) {
2729 myidx++;
2730 if (!*(args[myidx])) {
2731 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2732 file, linenum, args[myidx-1]);
2733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
2735 }
2736 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2737 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2738 file, linenum, *err, args[myidx-1]);
2739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
2741 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002742 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002743 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002744 else if (strcmp(args[myidx], "peers") == 0) {
2745 myidx++;
2746 if (!*(args[myidx])) {
2747 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2748 file, linenum, args[myidx-1]);
2749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
2751 }
2752 curproxy->table.peers.name = strdup(args[myidx++]);
2753 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002754 else if (strcmp(args[myidx], "expire") == 0) {
2755 myidx++;
2756 if (!*(args[myidx])) {
2757 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2758 file, linenum, args[myidx-1]);
2759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
2761 }
2762 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2763 if (err) {
2764 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2765 file, linenum, *err, args[myidx-1]);
2766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002770 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002771 }
2772 else if (strcmp(args[myidx], "nopurge") == 0) {
2773 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002774 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002775 }
2776 else if (strcmp(args[myidx], "type") == 0) {
2777 myidx++;
2778 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2779 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2780 file, linenum, args[myidx]);
2781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
2783 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002784 /* myidx already points to next arg */
2785 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002786 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002787 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002788 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002789
2790 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002791 nw = args[myidx];
2792 while (*nw) {
2793 /* the "store" keyword supports a comma-separated list */
2794 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002795 sa = NULL; /* store arg */
2796 while (*nw && *nw != ',') {
2797 if (*nw == '(') {
2798 *nw = 0;
2799 sa = ++nw;
2800 while (*nw != ')') {
2801 if (!*nw) {
2802 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2803 file, linenum, args[0], cw);
2804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
2807 nw++;
2808 }
2809 *nw = '\0';
2810 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002811 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002812 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002813 if (*nw)
2814 *nw++ = '\0';
2815 type = stktable_get_data_type(cw);
2816 if (type < 0) {
2817 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2818 file, linenum, args[0], cw);
2819 err_code |= ERR_ALERT | ERR_FATAL;
2820 goto out;
2821 }
Willy Tarreauac782882010-06-20 10:41:54 +02002822
2823 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2824 switch (err) {
2825 case PE_NONE: break;
2826 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002827 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2828 file, linenum, args[0], cw);
2829 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002830 break;
2831
2832 case PE_ARG_MISSING:
2833 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2834 file, linenum, args[0], cw);
2835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
2837
2838 case PE_ARG_NOT_USED:
2839 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2840 file, linenum, args[0], cw);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843
2844 default:
2845 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2846 file, linenum, args[0], cw);
2847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002849 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002850 }
2851 myidx++;
2852 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002853 else {
2854 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2855 file, linenum, args[myidx]);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002858 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002859 }
2860
2861 if (!curproxy->table.size) {
2862 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2863 file, linenum);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866 }
2867
2868 if (curproxy->table.type == (unsigned int)-1) {
2869 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2870 file, linenum);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874 }
2875 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002876 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002877 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002878 int myidx = 0;
2879 const char *name = NULL;
2880 int flags;
2881
2882 if (curproxy == &defproxy) {
2883 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
2887
2888 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2889 err_code |= ERR_WARN;
2890 goto out;
2891 }
2892
2893 myidx++;
2894 if ((strcmp(args[myidx], "store") == 0) ||
2895 (strcmp(args[myidx], "store-request") == 0)) {
2896 myidx++;
2897 flags = STK_IS_STORE;
2898 }
2899 else if (strcmp(args[myidx], "store-response") == 0) {
2900 myidx++;
2901 flags = STK_IS_STORE | STK_ON_RSP;
2902 }
2903 else if (strcmp(args[myidx], "match") == 0) {
2904 myidx++;
2905 flags = STK_IS_MATCH;
2906 }
2907 else if (strcmp(args[myidx], "on") == 0) {
2908 myidx++;
2909 flags = STK_IS_MATCH | STK_IS_STORE;
2910 }
2911 else {
2912 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
2916
2917 if (*(args[myidx]) == 0) {
2918 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
2921 }
2922
David du Colombier7af46052012-05-16 14:16:48 +02002923 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002924 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002925 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
2928 }
2929
2930 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002931 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002932 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2933 file, linenum, args[0], expr->fetch->kw);
2934 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002935 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002936 goto out;
2937 }
2938 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002939 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002940 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2941 file, linenum, args[0], expr->fetch->kw);
2942 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002943 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002944 goto out;
2945 }
2946 }
2947
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02002948 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
2949 if (expr->fetch->cap & SMP_CAP_L7)
2950 curproxy->acl_requires |= ACL_USE_L7_ANY;
2951
Emeric Brunb982a3d2010-01-04 15:45:53 +01002952 if (strcmp(args[myidx], "table") == 0) {
2953 myidx++;
2954 name = args[myidx++];
2955 }
2956
Willy Tarreauef6494c2010-01-28 17:12:36 +01002957 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002958 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
2959 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
2960 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002961 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002962 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002963 goto out;
2964 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002965 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002966 else if (*(args[myidx])) {
2967 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2968 file, linenum, args[0], args[myidx]);
2969 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002970 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002971 goto out;
2972 }
Emeric Brun97679e72010-09-23 17:56:44 +02002973 if (flags & STK_ON_RSP)
2974 err_code |= warnif_cond_requires_req(cond, file, linenum);
2975 else
2976 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002977
Emeric Brunb982a3d2010-01-04 15:45:53 +01002978 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2979 rule->cond = cond;
2980 rule->expr = expr;
2981 rule->flags = flags;
2982 rule->table.name = name ? strdup(name) : NULL;
2983 LIST_INIT(&rule->list);
2984 if (flags & STK_ON_RSP)
2985 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2986 else
2987 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002990 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002992
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2994 curproxy->uri_auth = NULL; /* we must detach from the default config */
2995
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002996 if (!*args[1]) {
2997 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002998 } else if (!strcmp(args[1], "admin")) {
2999 struct stats_admin_rule *rule;
3000
3001 if (curproxy == &defproxy) {
3002 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
3006
3007 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3008 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3009 err_code |= ERR_ALERT | ERR_ABORT;
3010 goto out;
3011 }
3012
3013 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3014 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3015 file, linenum, args[0], args[1]);
3016 err_code |= ERR_ALERT | ERR_FATAL;
3017 goto out;
3018 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003019 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3020 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3021 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
3026 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3027
3028 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3029 rule->cond = cond;
3030 LIST_INIT(&rule->list);
3031 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 } else if (!strcmp(args[1], "uri")) {
3033 if (*(args[2]) == 0) {
3034 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3038 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_ABORT;
3040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 }
3042 } else if (!strcmp(args[1], "realm")) {
3043 if (*(args[2]) == 0) {
3044 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3048 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_ABORT;
3050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003052 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003053 unsigned interval;
3054
3055 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3056 if (err) {
3057 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3058 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003061 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3062 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_ABORT;
3064 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003065 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003066 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003067 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003068
3069 if (curproxy == &defproxy) {
3070 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074
3075 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3076 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3077 err_code |= ERR_ALERT | ERR_ABORT;
3078 goto out;
3079 }
3080
Willy Tarreauff011f22011-01-06 17:51:27 +01003081 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3082 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003083 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3084 file, linenum, args[0]);
3085 err_code |= ERR_WARN;
3086 }
3087
Willy Tarreauff011f22011-01-06 17:51:27 +01003088 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003089
Willy Tarreauff011f22011-01-06 17:51:27 +01003090 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003091 err_code |= ERR_ALERT | ERR_ABORT;
3092 goto out;
3093 }
3094
Willy Tarreauff011f22011-01-06 17:51:27 +01003095 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3096 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003097
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 } else if (!strcmp(args[1], "auth")) {
3099 if (*(args[2]) == 0) {
3100 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3104 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_ABORT;
3106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 }
3108 } else if (!strcmp(args[1], "scope")) {
3109 if (*(args[2]) == 0) {
3110 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3114 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_ABORT;
3116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 }
3118 } else if (!strcmp(args[1], "enable")) {
3119 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3120 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003121 err_code |= ERR_ALERT | ERR_ABORT;
3122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003124 } else if (!strcmp(args[1], "hide-version")) {
3125 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_ABORT;
3128 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003129 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003130 } else if (!strcmp(args[1], "show-legends")) {
3131 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3132 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3133 err_code |= ERR_ALERT | ERR_ABORT;
3134 goto out;
3135 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003136 } else if (!strcmp(args[1], "show-node")) {
3137
3138 if (*args[2]) {
3139 int i;
3140 char c;
3141
3142 for (i=0; args[2][i]; i++) {
3143 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003144 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3145 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003146 break;
3147 }
3148
3149 if (!i || args[2][i]) {
3150 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3151 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3152 file, linenum, args[0], args[1]);
3153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
3155 }
3156 }
3157
3158 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3159 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3160 err_code |= ERR_ALERT | ERR_ABORT;
3161 goto out;
3162 }
3163 } else if (!strcmp(args[1], "show-desc")) {
3164 char *desc = NULL;
3165
3166 if (*args[2]) {
3167 int i, len=0;
3168 char *d;
3169
3170 for(i=2; *args[i]; i++)
3171 len += strlen(args[i])+1;
3172
3173 desc = d = (char *)calloc(1, len);
3174
3175 d += sprintf(d, "%s", args[2]);
3176 for(i=3; *args[i]; i++)
3177 d += sprintf(d, " %s", args[i]);
3178 }
3179
3180 if (!*args[2] && !global.desc)
3181 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3182 file, linenum, args[1]);
3183 else {
3184 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3185 free(desc);
3186 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3187 err_code |= ERR_ALERT | ERR_ABORT;
3188 goto out;
3189 }
3190 free(desc);
3191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003193stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003194 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 +01003195 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 }
3199 }
3200 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003201 int optnum;
3202
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003203 if (*(args[1]) == '\0') {
3204 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003209
3210 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3211 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003212 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3213 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3214 file, linenum, cfg_opts[optnum].name);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
Willy Tarreau93893792009-07-23 13:19:11 +02003218 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3219 err_code |= ERR_WARN;
3220 goto out;
3221 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003222
Willy Tarreau3842f002009-06-14 11:39:52 +02003223 curproxy->no_options &= ~cfg_opts[optnum].val;
3224 curproxy->options &= ~cfg_opts[optnum].val;
3225
3226 switch (kwm) {
3227 case KWM_STD:
3228 curproxy->options |= cfg_opts[optnum].val;
3229 break;
3230 case KWM_NO:
3231 curproxy->no_options |= cfg_opts[optnum].val;
3232 break;
3233 case KWM_DEF: /* already cleared */
3234 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003235 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003236
Willy Tarreau93893792009-07-23 13:19:11 +02003237 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003238 }
3239 }
3240
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003241 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3242 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003243 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3244 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3245 file, linenum, cfg_opts2[optnum].name);
3246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
3248 }
Willy Tarreau93893792009-07-23 13:19:11 +02003249 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3250 err_code |= ERR_WARN;
3251 goto out;
3252 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003253
Willy Tarreau3842f002009-06-14 11:39:52 +02003254 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3255 curproxy->options2 &= ~cfg_opts2[optnum].val;
3256
3257 switch (kwm) {
3258 case KWM_STD:
3259 curproxy->options2 |= cfg_opts2[optnum].val;
3260 break;
3261 case KWM_NO:
3262 curproxy->no_options2 |= cfg_opts2[optnum].val;
3263 break;
3264 case KWM_DEF: /* already cleared */
3265 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003266 }
Willy Tarreau93893792009-07-23 13:19:11 +02003267 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003268 }
3269 }
3270
Willy Tarreau3842f002009-06-14 11:39:52 +02003271 if (kwm != KWM_STD) {
3272 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003273 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003276 }
3277
Emeric Brun3a058f32009-06-30 18:26:00 +02003278 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003279 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003281 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003282 if (*(args[2]) != '\0') {
3283 if (!strcmp(args[2], "clf")) {
3284 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003285 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003286 } else {
3287 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003290 }
3291 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003292 if (curproxy->logformat_string != default_http_log_format &&
3293 curproxy->logformat_string != default_tcp_log_format &&
3294 curproxy->logformat_string != clf_http_log_format)
3295 free(curproxy->logformat_string);
3296 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003297 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003298 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003300 if (curproxy->logformat_string != default_http_log_format &&
3301 curproxy->logformat_string != default_tcp_log_format &&
3302 curproxy->logformat_string != clf_http_log_format)
3303 free(curproxy->logformat_string);
3304 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003305 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 else if (!strcmp(args[1], "tcpka")) {
3307 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003308 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003310
3311 if (curproxy->cap & PR_CAP_FE)
3312 curproxy->options |= PR_O_TCP_CLI_KA;
3313 if (curproxy->cap & PR_CAP_BE)
3314 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 }
3316 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003317 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_WARN;
3319
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003321 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003322 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003323 curproxy->options2 &= ~PR_O2_CHK_ANY;
3324 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 if (!*args[2]) { /* no argument */
3326 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3327 curproxy->check_len = strlen(DEF_CHECK_REQ);
3328 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003329 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 curproxy->check_req = (char *)malloc(reqlen);
3331 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003332 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003334 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 if (*args[4])
3336 reqlen += strlen(args[4]);
3337 else
3338 reqlen += strlen("HTTP/1.0");
3339
3340 curproxy->check_req = (char *)malloc(reqlen);
3341 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003342 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003344 }
3345 else if (!strcmp(args[1], "ssl-hello-chk")) {
3346 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003347 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003348 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003349
Willy Tarreaua534fea2008-08-03 12:19:50 +02003350 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003351 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003352 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003353 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354 }
Willy Tarreau23677902007-05-08 23:50:35 +02003355 else if (!strcmp(args[1], "smtpchk")) {
3356 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003357 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003358 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003359 curproxy->options2 &= ~PR_O2_CHK_ANY;
3360 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003361
3362 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3363 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3364 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3365 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3366 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3367 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3368 curproxy->check_req = (char *)malloc(reqlen);
3369 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3370 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3371 } else {
3372 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3373 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3374 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3375 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3376 }
3377 }
3378 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003379 else if (!strcmp(args[1], "pgsql-check")) {
3380 /* use PostgreSQL request to check servers' health */
3381 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3382 err_code |= ERR_WARN;
3383
3384 free(curproxy->check_req);
3385 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003386 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003387 curproxy->options2 |= PR_O2_PGSQL_CHK;
3388
3389 if (*(args[2])) {
3390 int cur_arg = 2;
3391
3392 while (*(args[cur_arg])) {
3393 if (strcmp(args[cur_arg], "user") == 0) {
3394 char * packet;
3395 uint32_t packet_len;
3396 uint32_t pv;
3397
3398 /* suboption header - needs additional argument for it */
3399 if (*(args[cur_arg+1]) == 0) {
3400 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3401 file, linenum, args[0], args[1], args[cur_arg]);
3402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
3404 }
3405
3406 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3407 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3408 pv = htonl(0x30000); /* protocol version 3.0 */
3409
3410 packet = (char*) calloc(1, packet_len);
3411
3412 memcpy(packet + 4, &pv, 4);
3413
3414 /* copy "user" */
3415 memcpy(packet + 8, "user", 4);
3416
3417 /* copy username */
3418 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3419
3420 free(curproxy->check_req);
3421 curproxy->check_req = packet;
3422 curproxy->check_len = packet_len;
3423
3424 packet_len = htonl(packet_len);
3425 memcpy(packet, &packet_len, 4);
3426 cur_arg += 2;
3427 } else {
3428 /* unknown suboption - catchall */
3429 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3430 file, linenum, args[0], args[1]);
3431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
3433 }
3434 } /* end while loop */
3435 }
3436 }
3437
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003438 else if (!strcmp(args[1], "redis-check")) {
3439 /* use REDIS PING request to check servers' health */
3440 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3441 err_code |= ERR_WARN;
3442
3443 free(curproxy->check_req);
3444 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003445 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003446 curproxy->options2 |= PR_O2_REDIS_CHK;
3447
3448 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3449 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3450 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3451 }
3452
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003453 else if (!strcmp(args[1], "mysql-check")) {
3454 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003455 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3456 err_code |= ERR_WARN;
3457
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003458 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003459 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003460 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003461 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003462
3463 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3464 * const char mysql40_client_auth_pkt[] = {
3465 * "\x0e\x00\x00" // packet length
3466 * "\x01" // packet number
3467 * "\x00\x00" // client capabilities
3468 * "\x00\x00\x01" // max packet
3469 * "haproxy\x00" // username (null terminated string)
3470 * "\x00" // filler (always 0x00)
3471 * "\x01\x00\x00" // packet length
3472 * "\x00" // packet number
3473 * "\x01" // COM_QUIT command
3474 * };
3475 */
3476
3477 if (*(args[2])) {
3478 int cur_arg = 2;
3479
3480 while (*(args[cur_arg])) {
3481 if (strcmp(args[cur_arg], "user") == 0) {
3482 char *mysqluser;
3483 int packetlen, reqlen, userlen;
3484
3485 /* suboption header - needs additional argument for it */
3486 if (*(args[cur_arg+1]) == 0) {
3487 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3488 file, linenum, args[0], args[1], args[cur_arg]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
3491 }
3492 mysqluser = args[cur_arg + 1];
3493 userlen = strlen(mysqluser);
3494 packetlen = userlen + 7;
3495 reqlen = packetlen + 9;
3496
3497 free(curproxy->check_req);
3498 curproxy->check_req = (char *)calloc(1, reqlen);
3499 curproxy->check_len = reqlen;
3500
3501 snprintf(curproxy->check_req, 4, "%c%c%c",
3502 ((unsigned char) packetlen & 0xff),
3503 ((unsigned char) (packetlen >> 8) & 0xff),
3504 ((unsigned char) (packetlen >> 16) & 0xff));
3505
3506 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003507 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003508 curproxy->check_req[8] = 1;
3509 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3510 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3511 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3512 cur_arg += 2;
3513 } else {
3514 /* unknown suboption - catchall */
3515 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3516 file, linenum, args[0], args[1]);
3517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
3519 }
3520 } /* end while loop */
3521 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003522 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003523 else if (!strcmp(args[1], "ldap-check")) {
3524 /* use LDAP request to check servers' health */
3525 free(curproxy->check_req);
3526 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003527 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003528 curproxy->options2 |= PR_O2_LDAP_CHK;
3529
3530 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3531 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3532 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3533 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003534 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003535 int cur_arg;
3536
3537 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3538 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003539 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003540
Willy Tarreau87cf5142011-08-19 22:57:24 +02003541 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003542
3543 free(curproxy->fwdfor_hdr_name);
3544 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3545 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3546
3547 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3548 cur_arg = 2;
3549 while (*(args[cur_arg])) {
3550 if (!strcmp(args[cur_arg], "except")) {
3551 /* suboption except - needs additional argument for it */
3552 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3553 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3554 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003557 }
3558 /* flush useless bits */
3559 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003560 cur_arg += 2;
3561 } else if (!strcmp(args[cur_arg], "header")) {
3562 /* suboption header - needs additional argument for it */
3563 if (*(args[cur_arg+1]) == 0) {
3564 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> 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;
Ross Westaf72a1d2008-08-03 10:51:45 +02003568 }
3569 free(curproxy->fwdfor_hdr_name);
3570 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3571 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3572 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003573 } else if (!strcmp(args[cur_arg], "if-none")) {
3574 curproxy->options &= ~PR_O_FF_ALWAYS;
3575 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003576 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003577 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003578 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003579 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003582 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003583 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003584 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003585 else if (!strcmp(args[1], "originalto")) {
3586 int cur_arg;
3587
3588 /* insert x-original-to field, but not for the IP address listed as an except.
3589 * set default options (ie: bitfield, header name, etc)
3590 */
3591
3592 curproxy->options |= PR_O_ORGTO;
3593
3594 free(curproxy->orgto_hdr_name);
3595 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3596 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3597
Willy Tarreau87cf5142011-08-19 22:57:24 +02003598 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003599 cur_arg = 2;
3600 while (*(args[cur_arg])) {
3601 if (!strcmp(args[cur_arg], "except")) {
3602 /* suboption except - needs additional argument for it */
3603 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3604 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3605 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003608 }
3609 /* flush useless bits */
3610 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3611 cur_arg += 2;
3612 } else if (!strcmp(args[cur_arg], "header")) {
3613 /* suboption header - needs additional argument for it */
3614 if (*(args[cur_arg+1]) == 0) {
3615 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3616 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003619 }
3620 free(curproxy->orgto_hdr_name);
3621 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3622 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3623 cur_arg += 2;
3624 } else {
3625 /* unknown suboption - catchall */
3626 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3627 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003630 }
3631 } /* end while loop */
3632 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 else {
3634 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 }
Willy Tarreau93893792009-07-23 13:19:11 +02003638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003640 else if (!strcmp(args[0], "default_backend")) {
3641 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003642 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003643
3644 if (*(args[1]) == 0) {
3645 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003648 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003649 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003650 curproxy->defbe.name = strdup(args[1]);
3651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003653 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003655
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003656 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3657 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 /* enable reconnections to dispatch */
3660 curproxy->options |= PR_O_REDISP;
3661 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003662 else if (!strcmp(args[0], "http-check")) {
3663 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003664 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003665
3666 if (strcmp(args[1], "disable-on-404") == 0) {
3667 /* enable a graceful server shutdown on an HTTP 404 response */
3668 curproxy->options |= PR_O_DISABLE404;
3669 }
Willy Tarreauef781042010-01-27 11:53:01 +01003670 else if (strcmp(args[1], "send-state") == 0) {
3671 /* enable emission of the apparent state of a server in HTTP checks */
3672 curproxy->options2 |= PR_O2_CHK_SNDST;
3673 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003674 else if (strcmp(args[1], "expect") == 0) {
3675 const char *ptr_arg;
3676 int cur_arg;
3677
3678 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3679 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
3682 }
3683
3684 cur_arg = 2;
3685 /* consider exclamation marks, sole or at the beginning of a word */
3686 while (*(ptr_arg = args[cur_arg])) {
3687 while (*ptr_arg == '!') {
3688 curproxy->options2 ^= PR_O2_EXP_INV;
3689 ptr_arg++;
3690 }
3691 if (*ptr_arg)
3692 break;
3693 cur_arg++;
3694 }
3695 /* now ptr_arg points to the beginning of a word past any possible
3696 * exclamation mark, and cur_arg is the argument which holds this word.
3697 */
3698 if (strcmp(ptr_arg, "status") == 0) {
3699 if (!*(args[cur_arg + 1])) {
3700 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3701 file, linenum, args[0], args[1], ptr_arg);
3702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
3704 }
3705 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003706 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003707 curproxy->expect_str = strdup(args[cur_arg + 1]);
3708 }
3709 else if (strcmp(ptr_arg, "string") == 0) {
3710 if (!*(args[cur_arg + 1])) {
3711 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3712 file, linenum, args[0], args[1], ptr_arg);
3713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
3715 }
3716 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003717 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003718 curproxy->expect_str = strdup(args[cur_arg + 1]);
3719 }
3720 else if (strcmp(ptr_arg, "rstatus") == 0) {
3721 if (!*(args[cur_arg + 1])) {
3722 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3723 file, linenum, args[0], args[1], ptr_arg);
3724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
3726 }
3727 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003728 free(curproxy->expect_str);
3729 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3730 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003731 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3732 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3733 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3734 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3735 err_code |= ERR_ALERT | ERR_FATAL;
3736 goto out;
3737 }
3738 }
3739 else if (strcmp(ptr_arg, "rstring") == 0) {
3740 if (!*(args[cur_arg + 1])) {
3741 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3742 file, linenum, args[0], args[1], ptr_arg);
3743 err_code |= ERR_ALERT | ERR_FATAL;
3744 goto out;
3745 }
3746 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003747 free(curproxy->expect_str);
3748 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3749 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003750 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3751 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3752 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3753 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
3756 }
3757 }
3758 else {
3759 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3760 file, linenum, args[0], args[1], ptr_arg);
3761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
3763 }
3764 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003765 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003766 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 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003769 }
3770 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003771 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003772 if (curproxy == &defproxy) {
3773 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003776 }
3777
Willy Tarreaub80c2302007-11-30 20:51:32 +01003778 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003780
3781 if (strcmp(args[1], "fail") == 0) {
3782 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003783 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003784 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3785 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003788 }
3789
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003790 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3791 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3792 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003795 }
3796 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3797 }
3798 else {
3799 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003802 }
3803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804#ifdef TPROXY
3805 else if (!strcmp(args[0], "transparent")) {
3806 /* enable transparent proxy connections */
3807 curproxy->options |= PR_O_TRANSP;
3808 }
3809#endif
3810 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003811 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003813
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 if (*(args[1]) == 0) {
3815 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 }
3819 curproxy->maxconn = atol(args[1]);
3820 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003821 else if (!strcmp(args[0], "backlog")) { /* backlog */
3822 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003824
3825 if (*(args[1]) == 0) {
3826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003829 }
3830 curproxy->backlog = atol(args[1]);
3831 }
Willy Tarreau86034312006-12-29 00:10:33 +01003832 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003833 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003835
Willy Tarreau86034312006-12-29 00:10:33 +01003836 if (*(args[1]) == 0) {
3837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003840 }
3841 curproxy->fullconn = atol(args[1]);
3842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3844 if (*(args[1]) == 0) {
3845 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003849 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3850 if (err) {
3851 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3852 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003855 }
3856 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
3858 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003859 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 if (curproxy == &defproxy) {
3861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003865 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003867
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 if (strchr(args[1], ':') == NULL) {
3869 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003873 sk = str2sa(args[1]);
3874 if (!sk) {
3875 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
3878 }
3879 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003880 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 }
3882 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003883 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003885
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003886 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3887 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003892 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3893 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3894 err_code |= ERR_WARN;
3895
3896 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3897 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3898 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3899 }
3900 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3901 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3902 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3903 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003904 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3905 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3906 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3907 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003908 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003909 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
3912 }
3913 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003914 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003916 char *rport, *raddr;
3917 short realport = 0;
3918 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003920 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003924 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003925 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927
3928 if (!*args[2]) {
3929 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003934
3935 err = invalid_char(args[1]);
3936 if (err) {
3937 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3938 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003941 }
3942
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003943 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003944 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003945
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003946 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3947 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3948 err_code |= ERR_ALERT | ERR_ABORT;
3949 goto out;
3950 }
3951
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003952 /* the servers are linked backwards first */
3953 newsrv->next = curproxy->srv;
3954 curproxy->srv = newsrv;
3955 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02003956 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003957 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003958
Simon Hormanaf514952011-06-21 14:34:57 +09003959 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003960 LIST_INIT(&newsrv->pendconns);
3961 do_check = 0;
3962 newsrv->state = SRV_RUNNING; /* early server setup */
3963 newsrv->last_change = now.tv_sec;
3964 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003965
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003966 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003967 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003968 * - IP: => port=+0, relative
3969 * - IP:N => port=N, absolute
3970 * - IP:+N => port=+N, relative
3971 * - IP:-N => port=-N, relative
3972 */
3973 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003974 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003975 if (rport) {
3976 *rport++ = 0;
3977 realport = atol(rport);
3978 if (!isdigit((unsigned char)*rport))
3979 newsrv->state |= SRV_MAPPORTS;
3980 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003982
Willy Tarreaufab5a432011-03-04 15:31:53 +01003983 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003984 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003985 if (!sk) {
3986 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
3990 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02003991 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
3992 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02003993
Willy Tarreau173e7fb2012-09-24 22:47:39 +02003994 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02003995 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
3996 file, linenum, newsrv->addr.ss_family, args[2]);
3997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004000 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004001
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004002 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004003 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004004 newsrv->inter = curproxy->defsrv.inter;
4005 newsrv->fastinter = curproxy->defsrv.fastinter;
4006 newsrv->downinter = curproxy->defsrv.downinter;
4007 newsrv->rise = curproxy->defsrv.rise;
4008 newsrv->fall = curproxy->defsrv.fall;
4009 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4010 newsrv->minconn = curproxy->defsrv.minconn;
4011 newsrv->maxconn = curproxy->defsrv.maxconn;
4012 newsrv->slowstart = curproxy->defsrv.slowstart;
4013 newsrv->onerror = curproxy->defsrv.onerror;
4014 newsrv->consecutive_errors_limit
4015 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004016#ifdef OPENSSL
4017 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4018#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004019 newsrv->uweight = newsrv->iweight
4020 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004022 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004024 cur_arg = 3;
4025 } else {
4026 newsrv = &curproxy->defsrv;
4027 cur_arg = 1;
4028 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004029
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004031 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004032 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004033
4034 if (!*args[cur_arg + 1]) {
4035 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4036 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004039 }
4040
4041 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004042 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004043
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004044 if (newsrv->puid <= 0) {
4045 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004046 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004049 }
4050
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004051 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4052 if (node) {
4053 struct server *target = container_of(node, struct server, conf.id);
4054 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4055 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4056 err_code |= ERR_ALERT | ERR_FATAL;
4057 goto out;
4058 }
4059 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004060 cur_arg += 2;
4061 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004062 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 newsrv->cookie = strdup(args[cur_arg + 1]);
4064 newsrv->cklen = strlen(args[cur_arg + 1]);
4065 cur_arg += 2;
4066 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004067 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004068 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4069 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4070 cur_arg += 2;
4071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004072 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004073 if (!*args[cur_arg + 1]) {
4074 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4075 file, linenum, args[cur_arg]);
4076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
4078 }
4079
Willy Tarreaubaaee002006-06-26 02:48:02 +02004080 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004081 if (newsrv->rise <= 0) {
4082 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4083 file, linenum, args[cur_arg]);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087
Willy Tarreau96839092010-03-29 10:02:24 +02004088 if (newsrv->health)
4089 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004090 cur_arg += 2;
4091 }
4092 else if (!strcmp(args[cur_arg], "fall")) {
4093 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004094
4095 if (!*args[cur_arg + 1]) {
4096 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4097 file, linenum, args[cur_arg]);
4098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
4100 }
4101
4102 if (newsrv->fall <= 0) {
4103 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4104 file, linenum, args[cur_arg]);
4105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
4107 }
4108
Willy Tarreaubaaee002006-06-26 02:48:02 +02004109 cur_arg += 2;
4110 }
4111 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004112 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4113 if (err) {
4114 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4115 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004118 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004119 if (val <= 0) {
4120 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4121 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004124 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004125 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 cur_arg += 2;
4127 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004128 else if (!strcmp(args[cur_arg], "fastinter")) {
4129 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4130 if (err) {
4131 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4132 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004135 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004136 if (val <= 0) {
4137 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4138 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004141 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004142 newsrv->fastinter = val;
4143 cur_arg += 2;
4144 }
Emeric Brun8694b9a2012-10-05 14:39:07 +02004145 else if (!strcmp(args[cur_arg], "force-sslv3")) {
4146#ifdef USE_OPENSSL
4147 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_SSLV3;
4148 cur_arg += 1;
4149#else /* USE_OPENSSL */
4150 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4151 file, linenum, args[cur_arg]);
4152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
4154#endif /* USE_OPENSSL */
4155 }
4156 else if (!strcmp(args[cur_arg], "force-tlsv10")) {
4157#ifdef USE_OPENSSL
4158 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV10;
4159 cur_arg += 1;
4160#else /* USE_OPENSSL */
4161 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4162 file, linenum, args[cur_arg]);
4163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
4165#endif /* USE_OPENSSL */
4166 }
4167 else if (!strcmp(args[cur_arg], "force-tlsv11")) {
4168#ifdef USE_OPENSSL
4169#if SSL_OP_NO_TLSv1_1
4170 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV11;
4171 cur_arg += 1;
4172#else
4173 Alert("parsing [%s:%d]: '%s' library does not support protocol TLSv1.1.\n",
4174 file, linenum, args[cur_arg]);
4175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
4177#endif
4178#else /* USE_OPENSSL */
4179 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4180 file, linenum, args[cur_arg]);
4181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
4183#endif /* USE_OPENSSL */
4184 }
4185 else if (!strcmp(args[cur_arg], "force-tlsv12")) {
4186#ifdef USE_OPENSSL
4187#if SSL_OP_NO_TLSv1_2
4188 newsrv->ssl_ctx.options |= SRV_SSL_O_USE_TLSV12;
4189 cur_arg += 1;
4190#else
4191 Alert("parsing [%s:%d]: '%s' library does not support protocol TLSv1.2.\n",
4192 file, linenum, args[cur_arg]);
4193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195#endif
4196#else /* USE_OPENSSL */
4197 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4198 file, linenum, args[cur_arg]);
4199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
4201#endif /* USE_OPENSSL */
4202 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004203 else if (!strcmp(args[cur_arg], "downinter")) {
4204 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4205 if (err) {
4206 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4207 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004210 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004211 if (val <= 0) {
4212 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4213 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004216 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004217 newsrv->downinter = val;
4218 cur_arg += 2;
4219 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004220 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004221 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004222 if (!sk) {
4223 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
4226 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004227 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004228 cur_arg += 2;
4229 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004231 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004232 cur_arg += 2;
4233 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004234 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004235 newsrv->state |= SRV_BACKUP;
4236 cur_arg ++;
4237 }
Simon Hormanfa461682011-06-25 09:39:49 +09004238 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4239 newsrv->state |= SRV_NON_STICK;
4240 cur_arg ++;
4241 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004242 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4243 newsrv->state |= SRV_SEND_PROXY;
4244 cur_arg ++;
4245 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004246 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4247 newsrv->check.send_proxy = 1;
4248 cur_arg ++;
4249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 else if (!strcmp(args[cur_arg], "weight")) {
4251 int w;
4252 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004253 if (w < 0 || w > 256) {
4254 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004259 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004260 cur_arg += 2;
4261 }
4262 else if (!strcmp(args[cur_arg], "minconn")) {
4263 newsrv->minconn = atol(args[cur_arg + 1]);
4264 cur_arg += 2;
4265 }
4266 else if (!strcmp(args[cur_arg], "maxconn")) {
4267 newsrv->maxconn = atol(args[cur_arg + 1]);
4268 cur_arg += 2;
4269 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004270 else if (!strcmp(args[cur_arg], "maxqueue")) {
4271 newsrv->maxqueue = atol(args[cur_arg + 1]);
4272 cur_arg += 2;
4273 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004274 else if (!strcmp(args[cur_arg], "slowstart")) {
4275 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004276 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004277 if (err) {
4278 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4279 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004282 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004283 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004284 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4285 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004288 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004289 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004290 cur_arg += 2;
4291 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004292 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004293
4294 if (!*args[cur_arg + 1]) {
4295 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4296 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004299 }
4300
4301 newsrv->trackit = strdup(args[cur_arg + 1]);
4302
4303 cur_arg += 2;
4304 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004305 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306 global.maxsock++;
4307 do_check = 1;
4308 cur_arg += 1;
4309 }
Willy Tarreau96839092010-03-29 10:02:24 +02004310 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4311 newsrv->state |= SRV_MAINTAIN;
4312 newsrv->state &= ~SRV_RUNNING;
4313 newsrv->health = 0;
4314 cur_arg += 1;
4315 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004316 else if (!strcmp(args[cur_arg], "ssl")) {
4317#ifdef USE_OPENSSL
4318 newsrv->use_ssl = 1;
4319 cur_arg += 1;
Emeric Brun76d88952012-10-05 15:47:31 +02004320
4321 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
4322 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004323#else /* USE_OPENSSL */
4324 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4325 file, linenum, args[cur_arg]);
4326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
4328#endif /* USE_OPENSSL */
4329 }
Willy Tarreau763a95b2012-10-04 23:15:39 +02004330 else if (!strcmp(args[cur_arg], "check-ssl")) {
4331#ifdef USE_OPENSSL
4332 newsrv->check.use_ssl = 1;
4333 cur_arg += 1;
Emeric Brun76d88952012-10-05 15:47:31 +02004334
4335 if (global.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
4336 newsrv->ssl_ctx.ciphers = strdup(global.connect_default_ciphers);
Willy Tarreau763a95b2012-10-04 23:15:39 +02004337#else /* USE_OPENSSL */
4338 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4339 file, linenum, args[cur_arg]);
4340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
4342#endif /* USE_OPENSSL */
4343 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004344 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4345#ifdef USE_OPENSSL
4346 if (!*args[cur_arg + 1]) {
4347 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4348 file, linenum, args[0], args[cur_arg]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 }
4352
Emeric Brun76d88952012-10-05 15:47:31 +02004353 free(newsrv->ssl_ctx.ciphers);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004354 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4355
4356 cur_arg += 2;
4357 continue;
4358#else
4359 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4360 file, linenum, args[0], args[cur_arg]);
4361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
4363#endif
4364 }
Emeric Brun9b3009b2012-10-05 11:55:06 +02004365 else if (!strcmp(args[cur_arg], "no-sslv3")) {
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004366#ifdef USE_OPENSSL
Emeric Brun89675492012-10-05 13:48:26 +02004367 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_SSLV3;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004368 cur_arg += 1;
4369#else /* USE_OPENSSL */
4370 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4371 file, linenum, args[cur_arg]);
4372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
4374#endif /* USE_OPENSSL */
4375 }
Emeric Brun9b3009b2012-10-05 11:55:06 +02004376 else if (!strcmp(args[cur_arg], "no-tlsv10")) {
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004377#ifdef USE_OPENSSL
Emeric Brun89675492012-10-05 13:48:26 +02004378 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV10;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004379 cur_arg += 1;
4380#else /* USE_OPENSSL */
4381 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4382 file, linenum, args[cur_arg]);
4383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
4385#endif /* USE_OPENSSL */
4386 }
Emeric Brun9b3009b2012-10-05 11:55:06 +02004387 else if (!strcmp(args[cur_arg], "no-tlsv11")) {
Emeric Brunc0ff4922012-09-28 19:37:02 +02004388#ifdef USE_OPENSSL
Emeric Brun89675492012-10-05 13:48:26 +02004389 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV11;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004390 cur_arg += 1;
4391#else /* USE_OPENSSL */
4392 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4393 file, linenum, args[cur_arg]);
4394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
4396#endif /* USE_OPENSSL */
4397 }
Emeric Brun9b3009b2012-10-05 11:55:06 +02004398 else if (!strcmp(args[cur_arg], "no-tlsv12")) {
Emeric Brunc0ff4922012-09-28 19:37:02 +02004399#ifdef USE_OPENSSL
Emeric Brun89675492012-10-05 13:48:26 +02004400 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLSV12;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004401 cur_arg += 1;
4402#else /* USE_OPENSSL */
4403 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4404 file, linenum, args[cur_arg]);
4405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
4407#endif /* USE_OPENSSL */
4408 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004409 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004410 if (!strcmp(args[cur_arg + 1], "none"))
4411 newsrv->observe = HANA_OBS_NONE;
4412 else if (!strcmp(args[cur_arg + 1], "layer4"))
4413 newsrv->observe = HANA_OBS_LAYER4;
4414 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4415 if (curproxy->mode != PR_MODE_HTTP) {
4416 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4417 file, linenum, args[cur_arg + 1]);
4418 err_code |= ERR_ALERT;
4419 }
4420 newsrv->observe = HANA_OBS_LAYER7;
4421 }
4422 else {
4423 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004424 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004425 file, linenum, args[cur_arg], args[cur_arg + 1]);
4426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
4428 }
4429
4430 cur_arg += 2;
4431 }
4432 else if (!strcmp(args[cur_arg], "on-error")) {
4433 if (!strcmp(args[cur_arg + 1], "fastinter"))
4434 newsrv->onerror = HANA_ONERR_FASTINTER;
4435 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4436 newsrv->onerror = HANA_ONERR_FAILCHK;
4437 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4438 newsrv->onerror = HANA_ONERR_SUDDTH;
4439 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4440 newsrv->onerror = HANA_ONERR_MARKDWN;
4441 else {
4442 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004443 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004444 file, linenum, args[cur_arg], args[cur_arg + 1]);
4445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
4447 }
4448
4449 cur_arg += 2;
4450 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004451 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4452 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4453 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4454 else {
4455 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4456 file, linenum, args[cur_arg], args[cur_arg + 1]);
4457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
4459 }
4460
4461 cur_arg += 2;
4462 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004463 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4464 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4465 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4466 else {
4467 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4468 file, linenum, args[cur_arg], args[cur_arg + 1]);
4469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
4471 }
4472
4473 cur_arg += 2;
4474 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004475 else if (!strcmp(args[cur_arg], "error-limit")) {
4476 if (!*args[cur_arg + 1]) {
4477 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4478 file, linenum, args[cur_arg]);
4479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
4481 }
4482
4483 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4484
4485 if (newsrv->consecutive_errors_limit <= 0) {
4486 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4487 file, linenum, args[cur_arg]);
4488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
4490 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004491 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004492 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004493 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004494 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004495 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004496
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004498#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004499 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004500 file, linenum, "source", "usesrc");
4501#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004502 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004504#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 }
4508 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004509 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4510 if (!sk) {
4511 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
4514 }
4515 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004516
4517 if (port_low != port_high) {
4518 int i;
4519 if (port_low <= 0 || port_low > 65535 ||
4520 port_high <= 0 || port_high > 65535 ||
4521 port_low > port_high) {
4522 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4523 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004526 }
4527 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4528 for (i = 0; i < newsrv->sport_range->size; i++)
4529 newsrv->sport_range->ports[i] = port_low + i;
4530 }
4531
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004533 while (*(args[cur_arg])) {
4534 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004535#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4536#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004537 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4538 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4539 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004542 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004543#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004544 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004545 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004546 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004549 }
4550 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004551 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004552 newsrv->state |= SRV_TPROXY_CLI;
4553 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004554 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004555 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004556 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4557 char *name, *end;
4558
4559 name = args[cur_arg+1] + 7;
4560 while (isspace(*name))
4561 name++;
4562
4563 end = name;
4564 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4565 end++;
4566
4567 newsrv->state &= ~SRV_TPROXY_MASK;
4568 newsrv->state |= SRV_TPROXY_DYN;
4569 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4570 newsrv->bind_hdr_len = end - name;
4571 memcpy(newsrv->bind_hdr_name, name, end - name);
4572 newsrv->bind_hdr_name[end-name] = '\0';
4573 newsrv->bind_hdr_occ = -1;
4574
4575 /* now look for an occurrence number */
4576 while (isspace(*end))
4577 end++;
4578 if (*end == ',') {
4579 end++;
4580 name = end;
4581 if (*end == '-')
4582 end++;
4583 while (isdigit(*end))
4584 end++;
4585 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4586 }
4587
4588 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4589 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4590 " occurrences values smaller than %d.\n",
4591 file, linenum, MAX_HDR_HISTORY);
4592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
4594 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004595 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004596 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004597 if (!sk) {
4598 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
4601 }
4602 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004603 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004604 }
4605 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004606#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004607 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004608#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004609 cur_arg += 2;
4610 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004611#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004612 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004613 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004616#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4617 } /* "usesrc" */
4618
4619 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4620#ifdef SO_BINDTODEVICE
4621 if (!*args[cur_arg + 1]) {
4622 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004624 err_code |= ERR_ALERT | ERR_FATAL;
4625 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004626 }
4627 if (newsrv->iface_name)
4628 free(newsrv->iface_name);
4629
4630 newsrv->iface_name = strdup(args[cur_arg + 1]);
4631 newsrv->iface_len = strlen(newsrv->iface_name);
4632 global.last_checks |= LSTCHK_NETADM;
4633#else
4634 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4635 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004638#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004639 cur_arg += 2;
4640 continue;
4641 }
4642 /* this keyword in not an option of "source" */
4643 break;
4644 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004645 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004646 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004647 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4648 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004649 err_code |= ERR_ALERT | ERR_FATAL;
4650 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004653 static int srv_dumped;
4654 struct srv_kw *kw;
4655 char *err;
4656
4657 kw = srv_find_kw(args[cur_arg]);
4658 if (kw) {
4659 char *err = NULL;
4660 int code;
4661
4662 if (!kw->parse) {
4663 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4664 file, linenum, args[0], args[1], args[cur_arg]);
4665 cur_arg += 1 + kw->skip ;
4666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
4668 }
4669
4670 if (defsrv && !kw->default_ok) {
4671 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4672 file, linenum, args[0], args[1], args[cur_arg]);
4673 cur_arg += 1 + kw->skip ;
4674 err_code |= ERR_ALERT;
4675 continue;
4676 }
4677
4678 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4679 err_code |= code;
4680
4681 if (code) {
4682 if (err && *err) {
4683 indent_msg(&err, 2);
4684 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4685 }
4686 else
4687 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4688 file, linenum, args[0], args[1], args[cur_arg]);
4689 if (code & ERR_FATAL) {
4690 free(err);
4691 cur_arg += 1 + kw->skip;
4692 goto out;
4693 }
4694 }
4695 free(err);
4696 cur_arg += 1 + kw->skip;
4697 continue;
4698 }
4699
4700 err = NULL;
4701 if (!srv_dumped) {
4702 srv_dump_kws(&err);
4703 indent_msg(&err, 4);
4704 srv_dumped = 1;
4705 }
4706
4707 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4708 file, linenum, args[0], args[1], args[cur_arg],
4709 err ? " Registered keywords :" : "", err ? err : "");
4710 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004711
Willy Tarreau93893792009-07-23 13:19:11 +02004712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 }
4715 }
4716
4717 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004718 if (newsrv->trackit) {
4719 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4720 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004721 err_code |= ERR_ALERT | ERR_FATAL;
4722 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004723 }
4724
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004725 /* If neither a port nor an addr was specified and no check transport
4726 * layer is forced, then the transport layer used by the checks is the
4727 * same as for the production traffic. Otherwise we use raw_sock by
4728 * default, unless one is specified.
4729 */
Baptiste Assmanne6baecf2012-10-05 11:48:04 +02004730#ifdef USE_OPENSSL
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004731 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004732 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004733 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4734 }
Baptiste Assmanne6baecf2012-10-05 11:48:04 +02004735#endif
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004736 /* try to get the port from check.addr if check.port not set */
4737 if (!newsrv->check.port)
4738 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004739
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004740 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4741 newsrv->check.port = realport; /* by default */
4742 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004743 /* not yet valid, because no port was set on
4744 * the server either. We'll check if we have
4745 * a known port on the first listener.
4746 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004747 struct listener *l;
4748
4749 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004750 newsrv->check.port = get_host_port(&l->addr);
4751 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004752 break;
4753 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004754 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004755 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4757 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004761
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004762 /* Allocate buffer for check requests... */
4763 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004764 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4765 err_code |= ERR_ALERT | ERR_ABORT;
4766 goto out;
4767 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004768 newsrv->check.bi->size = global.tune.chksize;
4769
4770 /* Allocate buffer for check responses... */
4771 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4772 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4773 err_code |= ERR_ALERT | ERR_ABORT;
4774 goto out;
4775 }
4776 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004777
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004778 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004779 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004780 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4781 err_code |= ERR_ALERT | ERR_ABORT;
4782 goto out;
4783 }
4784
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004785 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4786 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 newsrv->state |= SRV_CHECKED;
4788 }
4789
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004790 if (!defsrv) {
4791 if (newsrv->state & SRV_BACKUP)
4792 curproxy->srv_bck++;
4793 else
4794 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004795
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004796 newsrv->prev_state = newsrv->state;
4797 }
William Lallemanda73203e2012-03-12 12:48:57 +01004798 }
4799
4800 else if (strcmp(args[0], "unique-id-format") == 0) {
4801 if (!*(args[1])) {
4802 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4803 err_code |= ERR_ALERT | ERR_FATAL;
4804 goto out;
4805 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004806 free(curproxy->uniqueid_format_string);
4807 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004808 }
William Lallemanda73203e2012-03-12 12:48:57 +01004809
4810 else if (strcmp(args[0], "unique-id-header") == 0) {
4811 if (!*(args[1])) {
4812 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
4815 }
4816 free(curproxy->header_unique_id);
4817 curproxy->header_unique_id = strdup(args[1]);
4818 }
4819
William Lallemand723b73a2012-02-08 16:37:49 +01004820 else if (strcmp(args[0], "log-format") == 0) {
4821 if (!*(args[1])) {
4822 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4823 err_code |= ERR_ALERT | ERR_FATAL;
4824 goto out;
4825 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004826
4827 if (curproxy->logformat_string != default_http_log_format &&
4828 curproxy->logformat_string != default_tcp_log_format &&
4829 curproxy->logformat_string != clf_http_log_format)
4830 free(curproxy->logformat_string);
4831 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 }
William Lallemand723b73a2012-02-08 16:37:49 +01004833
William Lallemand0f99e342011-10-12 17:50:54 +02004834 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4835 /* delete previous herited or defined syslog servers */
4836 struct logsrv *back;
4837
4838 if (*(args[1]) != 0) {
4839 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4840 err_code |= ERR_ALERT | ERR_FATAL;
4841 goto out;
4842 }
4843
William Lallemand723b73a2012-02-08 16:37:49 +01004844 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4845 LIST_DEL(&tmplogsrv->list);
4846 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004847 }
4848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004850 struct logsrv *logsrv;
4851
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004853 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004854 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004855 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004856 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004857 LIST_INIT(&node->list);
4858 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 }
4861 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004862
4863 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864
William Lallemand0f99e342011-10-12 17:50:54 +02004865 logsrv->facility = get_log_facility(args[2]);
4866 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
4870
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
4872
William Lallemand0f99e342011-10-12 17:50:54 +02004873 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004875 logsrv->level = get_log_level(args[3]);
4876 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
4880
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 }
4882 }
4883
William Lallemand0f99e342011-10-12 17:50:54 +02004884 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004885 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004886 logsrv->minlvl = get_log_level(args[4]);
4887 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004888 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004889 err_code |= ERR_ALERT | ERR_FATAL;
4890 goto out;
4891
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004892 }
4893 }
4894
Robert Tsai81ae1952007-12-05 10:47:29 +01004895 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004896 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004897 if (!sk) {
4898 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004899 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
4902 }
William Lallemand0f99e342011-10-12 17:50:54 +02004903 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004904 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004905 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004906 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004907 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
4910 }
William Lallemand0f99e342011-10-12 17:50:54 +02004911 logsrv->addr = *sk;
4912 if (!get_host_port(&logsrv->addr))
4913 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 }
William Lallemand0f99e342011-10-12 17:50:54 +02004915
4916 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 }
4918 else {
4919 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4920 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 }
4924 }
4925 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004926 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004927 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004928
Willy Tarreau977b8e42006-12-29 14:19:17 +01004929 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004930 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004931
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004933 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4934 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004935 err_code |= ERR_ALERT | ERR_FATAL;
4936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004938
4939 /* we must first clear any optional default setting */
4940 curproxy->options &= ~PR_O_TPXY_MASK;
4941 free(curproxy->iface_name);
4942 curproxy->iface_name = NULL;
4943 curproxy->iface_len = 0;
4944
Willy Tarreaud5191e72010-02-09 20:50:45 +01004945 sk = str2sa(args[1]);
4946 if (!sk) {
4947 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
4950 }
4951 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004953
4954 cur_arg = 2;
4955 while (*(args[cur_arg])) {
4956 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004957#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4958#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004959 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4960 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4961 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004962 err_code |= ERR_ALERT | ERR_FATAL;
4963 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004964 }
4965#endif
4966 if (!*args[cur_arg + 1]) {
4967 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4968 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004971 }
4972
4973 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004974 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004975 curproxy->options |= PR_O_TPXY_CLI;
4976 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004977 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004978 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004979 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4980 char *name, *end;
4981
4982 name = args[cur_arg+1] + 7;
4983 while (isspace(*name))
4984 name++;
4985
4986 end = name;
4987 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4988 end++;
4989
4990 curproxy->options &= ~PR_O_TPXY_MASK;
4991 curproxy->options |= PR_O_TPXY_DYN;
4992 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4993 curproxy->bind_hdr_len = end - name;
4994 memcpy(curproxy->bind_hdr_name, name, end - name);
4995 curproxy->bind_hdr_name[end-name] = '\0';
4996 curproxy->bind_hdr_occ = -1;
4997
4998 /* now look for an occurrence number */
4999 while (isspace(*end))
5000 end++;
5001 if (*end == ',') {
5002 end++;
5003 name = end;
5004 if (*end == '-')
5005 end++;
5006 while (isdigit(*end))
5007 end++;
5008 curproxy->bind_hdr_occ = strl2ic(name, end-name);
5009 }
5010
5011 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
5012 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5013 " occurrences values smaller than %d.\n",
5014 file, linenum, MAX_HDR_HISTORY);
5015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
5017 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005018 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005019 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005020 if (!sk) {
5021 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5022 err_code |= ERR_ALERT | ERR_FATAL;
5023 goto out;
5024 }
5025 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005026 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005027 }
5028 global.last_checks |= LSTCHK_NETADM;
5029#if !defined(CONFIG_HAP_LINUX_TPROXY)
5030 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005031#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005032#else /* no TPROXY support */
5033 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005034 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005037#endif
5038 cur_arg += 2;
5039 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005040 }
5041
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005042 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5043#ifdef SO_BINDTODEVICE
5044 if (!*args[cur_arg + 1]) {
5045 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005049 }
5050 if (curproxy->iface_name)
5051 free(curproxy->iface_name);
5052
5053 curproxy->iface_name = strdup(args[cur_arg + 1]);
5054 curproxy->iface_len = strlen(curproxy->iface_name);
5055 global.last_checks |= LSTCHK_NETADM;
5056#else
5057 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5058 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005061#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005062 cur_arg += 2;
5063 continue;
5064 }
5065 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005066 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005069 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005071 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5072 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5073 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5080 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005084
5085 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005086 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005087 args[0], args[1], args[2], (const char **)args+3);
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], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005092 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005093 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005094 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005095 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097 }
5098 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005099 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005100 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005101 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005102 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 }
5105 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005106 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005107 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005108 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 }
5112 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005113 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005114 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005115 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005116 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005119 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005121 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005122 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005123 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005124 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005125 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005126 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005127 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005128 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005129 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005130 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005131 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005132 }
5133 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005135 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005136 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005137 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005138 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005139 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5143 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005146 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147
5148 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005149 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005150 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 }
5154 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005156 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005157 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005158 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 }
5161 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005163 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005164 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005165 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 }
5168 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005169 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005170 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005171 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 }
5175 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005177 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005178 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005179 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005182 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005183 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005184 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005185 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005186 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005187 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005188 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005189 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005190 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005191
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 if (curproxy == &defproxy) {
5193 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005197 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005198 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199
Willy Tarreaubaaee002006-06-26 02:48:02 +02005200 if (*(args[1]) == 0) {
5201 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005205
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005206 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005207 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5208 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5209 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005210 err_code |= ERR_ALERT | ERR_FATAL;
5211 goto out;
5212 }
5213 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5214 }
5215 else if (*args[2]) {
5216 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5217 file, linenum, args[0], args[2]);
5218 err_code |= ERR_ALERT | ERR_FATAL;
5219 goto out;
5220 }
5221
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005222 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005223 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005224 wl->s = strdup(args[1]);
5225 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005226 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 }
5228 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005229 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5231 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005234 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005235
Willy Tarreauade5ec42010-01-28 19:33:49 +01005236 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005237 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005238 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241 }
5242 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005243 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005244 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005245 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 }
5249 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005250 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005251 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005252 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005255 }
5256 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005257 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5259 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 }
5263
Willy Tarreauade5ec42010-01-28 19:33:49 +01005264 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005265 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005266 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269 }
5270 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005271 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005272 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005273 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276 }
5277 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005278 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005279 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005280 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005281 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 }
5284 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005285 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005286
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 if (curproxy == &defproxy) {
5288 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005292 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005293 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 if (*(args[1]) == 0) {
5296 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 }
5300
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005301 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005302 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5303 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5304 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005305 err_code |= ERR_ALERT | ERR_FATAL;
5306 goto out;
5307 }
5308 err_code |= warnif_cond_requires_req(cond, file, linenum);
5309 }
5310 else if (*args[2]) {
5311 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5312 file, linenum, args[0], args[2]);
5313 err_code |= ERR_ALERT | ERR_FATAL;
5314 goto out;
5315 }
5316
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005317 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005318 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005319 wl->s = strdup(args[1]);
5320 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 }
5322 else if (!strcmp(args[0], "errorloc") ||
5323 !strcmp(args[0], "errorloc302") ||
5324 !strcmp(args[0], "errorloc303")) { /* error location */
5325 int errnum, errlen;
5326 char *err;
5327
Willy Tarreau977b8e42006-12-29 14:19:17 +01005328 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005329 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005330
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005332 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 }
5336
5337 errnum = atol(args[1]);
5338 if (!strcmp(args[0], "errorloc303")) {
5339 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5340 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5341 } else {
5342 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5343 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5344 }
5345
Willy Tarreau0f772532006-12-23 20:51:41 +01005346 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5347 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005348 chunk_destroy(&curproxy->errmsg[rc]);
5349 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005350 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005353
5354 if (rc >= HTTP_ERR_SIZE) {
5355 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5356 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005357 free(err);
5358 }
5359 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005360 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5361 int errnum, errlen, fd;
5362 char *err;
5363 struct stat stat;
5364
5365 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005366 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005367
5368 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005369 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005372 }
5373
5374 fd = open(args[2], O_RDONLY);
5375 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5376 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5377 file, linenum, args[2], args[1]);
5378 if (fd >= 0)
5379 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005382 }
5383
Willy Tarreau27a674e2009-08-17 07:23:33 +02005384 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005385 errlen = stat.st_size;
5386 } else {
5387 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005388 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005389 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005390 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005391 }
5392
5393 err = malloc(errlen); /* malloc() must succeed during parsing */
5394 errnum = read(fd, err, errlen);
5395 if (errnum != errlen) {
5396 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5397 file, linenum, args[2], args[1]);
5398 close(fd);
5399 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005400 err_code |= ERR_ALERT | ERR_FATAL;
5401 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005402 }
5403 close(fd);
5404
5405 errnum = atol(args[1]);
5406 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5407 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005408 chunk_destroy(&curproxy->errmsg[rc]);
5409 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005410 break;
5411 }
5412 }
5413
5414 if (rc >= HTTP_ERR_SIZE) {
5415 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5416 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005417 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005418 free(err);
5419 }
5420 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005422 struct cfg_kw_list *kwl;
5423 int index;
5424
5425 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5426 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5427 if (kwl->kw[index].section != CFG_LISTEN)
5428 continue;
5429 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5430 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005431 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005432 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau28a47d62012-09-18 20:02:48 +02005433 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005434 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005435 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005436 err_code |= ERR_ALERT | ERR_FATAL;
5437 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005438 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005439 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005440 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005441 err_code |= ERR_WARN;
5442 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005443 }
Willy Tarreau93893792009-07-23 13:19:11 +02005444 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005445 }
5446 }
5447 }
5448
Willy Tarreau6daf3432008-01-22 16:44:08 +01005449 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005450 err_code |= ERR_ALERT | ERR_FATAL;
5451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005452 }
Willy Tarreau93893792009-07-23 13:19:11 +02005453 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005454 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005455 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005456}
5457
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005458int
5459cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5460{
5461
5462 int err_code = 0;
5463 const char *err;
5464
5465 if (!strcmp(args[0], "userlist")) { /* new userlist */
5466 struct userlist *newul;
5467
5468 if (!*args[1]) {
5469 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5470 file, linenum, args[0]);
5471 err_code |= ERR_ALERT | ERR_FATAL;
5472 goto out;
5473 }
5474
5475 err = invalid_char(args[1]);
5476 if (err) {
5477 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5478 file, linenum, *err, args[0], args[1]);
5479 err_code |= ERR_ALERT | ERR_FATAL;
5480 goto out;
5481 }
5482
5483 for (newul = userlist; newul; newul = newul->next)
5484 if (!strcmp(newul->name, args[1])) {
5485 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5486 file, linenum, args[1]);
5487 err_code |= ERR_WARN;
5488 goto out;
5489 }
5490
5491 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5492 if (!newul) {
5493 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5494 err_code |= ERR_ALERT | ERR_ABORT;
5495 goto out;
5496 }
5497
5498 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5499 newul->name = strdup(args[1]);
5500
5501 if (!newul->groupusers | !newul->name) {
5502 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5503 err_code |= ERR_ALERT | ERR_ABORT;
5504 goto out;
5505 }
5506
5507 newul->next = userlist;
5508 userlist = newul;
5509
5510 } else if (!strcmp(args[0], "group")) { /* new group */
5511 int cur_arg, i;
5512 const char *err;
5513
5514 if (!*args[1]) {
5515 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5516 file, linenum, args[0]);
5517 err_code |= ERR_ALERT | ERR_FATAL;
5518 goto out;
5519 }
5520
5521 err = invalid_char(args[1]);
5522 if (err) {
5523 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5524 file, linenum, *err, args[0], args[1]);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
5528
5529 for(i = 0; i < userlist->grpcnt; i++)
5530 if (!strcmp(userlist->groups[i], args[1])) {
5531 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5532 file, linenum, args[1], userlist->name);
5533 err_code |= ERR_ALERT;
5534 goto out;
5535 }
5536
5537 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5538 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5539 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5540 err_code |= ERR_ALERT | ERR_FATAL;
5541 goto out;
5542 }
5543
5544 cur_arg = 2;
5545
5546 while (*args[cur_arg]) {
5547 if (!strcmp(args[cur_arg], "users")) {
5548 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5549 cur_arg += 2;
5550 continue;
5551 } else {
5552 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5553 file, linenum, args[0]);
5554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
5556 }
5557 }
5558
5559 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5560 } else if (!strcmp(args[0], "user")) { /* new user */
5561 struct auth_users *newuser;
5562 int cur_arg;
5563
5564 if (!*args[1]) {
5565 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5566 file, linenum, args[0]);
5567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
5569 }
5570
5571 for (newuser = userlist->users; newuser; newuser = newuser->next)
5572 if (!strcmp(newuser->user, args[1])) {
5573 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5574 file, linenum, args[1], userlist->name);
5575 err_code |= ERR_ALERT;
5576 goto out;
5577 }
5578
5579 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5580 if (!newuser) {
5581 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5582 err_code |= ERR_ALERT | ERR_ABORT;
5583 goto out;
5584 }
5585
5586 newuser->user = strdup(args[1]);
5587
5588 newuser->next = userlist->users;
5589 userlist->users = newuser;
5590
5591 cur_arg = 2;
5592
5593 while (*args[cur_arg]) {
5594 if (!strcmp(args[cur_arg], "password")) {
5595#ifndef CONFIG_HAP_CRYPT
5596 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5597 file, linenum);
5598 err_code |= ERR_ALERT;
5599#endif
5600 newuser->pass = strdup(args[cur_arg + 1]);
5601 cur_arg += 2;
5602 continue;
5603 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5604 newuser->pass = strdup(args[cur_arg + 1]);
5605 newuser->flags |= AU_O_INSECURE;
5606 cur_arg += 2;
5607 continue;
5608 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005609 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005610 cur_arg += 2;
5611 continue;
5612 } else {
5613 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5614 file, linenum, args[0]);
5615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
5617 }
5618 }
5619 } else {
5620 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5621 err_code |= ERR_ALERT | ERR_FATAL;
5622 }
5623
5624out:
5625 return err_code;
5626}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627
5628/*
5629 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005630 * Returns the error code, 0 if OK, or any combination of :
5631 * - ERR_ABORT: must abort ASAP
5632 * - ERR_FATAL: we can continue parsing but not start the service
5633 * - ERR_WARN: a warning has been emitted
5634 * - ERR_ALERT: an alert has been emitted
5635 * Only the two first ones can stop processing, the two others are just
5636 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005637 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005638int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005640 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 FILE *f;
5642 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005644 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645
Willy Tarreaubaaee002006-06-26 02:48:02 +02005646 if ((f=fopen(file,"r")) == NULL)
5647 return -1;
5648
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005649 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005650 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005651 char *end;
5652 char *args[MAX_LINE_ARGS + 1];
5653 char *line = thisline;
5654
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 linenum++;
5656
5657 end = line + strlen(line);
5658
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005659 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5660 /* Check if we reached the limit and the last char is not \n.
5661 * Watch out for the last line without the terminating '\n'!
5662 */
5663 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005664 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005665 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005666 }
5667
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005669 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 line++;
5671
5672 arg = 0;
5673 args[arg] = line;
5674
5675 while (*line && arg < MAX_LINE_ARGS) {
5676 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5677 * C equivalent value. Other combinations left unchanged (eg: \1).
5678 */
5679 if (*line == '\\') {
5680 int skip = 0;
5681 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5682 *line = line[1];
5683 skip = 1;
5684 }
5685 else if (line[1] == 'r') {
5686 *line = '\r';
5687 skip = 1;
5688 }
5689 else if (line[1] == 'n') {
5690 *line = '\n';
5691 skip = 1;
5692 }
5693 else if (line[1] == 't') {
5694 *line = '\t';
5695 skip = 1;
5696 }
5697 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005698 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699 unsigned char hex1, hex2;
5700 hex1 = toupper(line[2]) - '0';
5701 hex2 = toupper(line[3]) - '0';
5702 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5703 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5704 *line = (hex1<<4) + hex2;
5705 skip = 3;
5706 }
5707 else {
5708 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005709 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 }
5711 }
5712 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005713 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714 end -= skip;
5715 }
5716 line++;
5717 }
5718 else if (*line == '#' || *line == '\n' || *line == '\r') {
5719 /* end of string, end of loop */
5720 *line = 0;
5721 break;
5722 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005723 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005725 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005726 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 line++;
5728 args[++arg] = line;
5729 }
5730 else {
5731 line++;
5732 }
5733 }
5734
5735 /* empty line */
5736 if (!**args)
5737 continue;
5738
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005739 if (*line) {
5740 /* we had to stop due to too many args.
5741 * Let's terminate the string, print the offending part then cut the
5742 * last arg.
5743 */
5744 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5745 line++;
5746 *line = '\0';
5747
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005748 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005749 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005750 err_code |= ERR_ALERT | ERR_FATAL;
5751 args[arg] = line;
5752 }
5753
Willy Tarreau540abe42007-05-02 20:50:16 +02005754 /* zero out remaining args and ensure that at least one entry
5755 * is zeroed out.
5756 */
5757 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005758 args[arg] = line;
5759 }
5760
Willy Tarreau3842f002009-06-14 11:39:52 +02005761 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005762 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005763 char *tmp;
5764
Willy Tarreau3842f002009-06-14 11:39:52 +02005765 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005766 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005767 for (arg=0; *args[arg+1]; arg++)
5768 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005769 *tmp = '\0'; // fix the next arg to \0
5770 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005771 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005772 else if (!strcmp(args[0], "default")) {
5773 kwm = KWM_DEF;
5774 for (arg=0; *args[arg+1]; arg++)
5775 args[arg] = args[arg+1]; // shift args after inversion
5776 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005777
William Lallemand0f99e342011-10-12 17:50:54 +02005778 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5779 strcmp(args[0], "log") != 0) {
5780 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005781 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005782 }
5783
Willy Tarreau977b8e42006-12-29 14:19:17 +01005784 if (!strcmp(args[0], "listen") ||
5785 !strcmp(args[0], "frontend") ||
5786 !strcmp(args[0], "backend") ||
5787 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005788 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005790 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005791 cursection = strdup(args[0]);
5792 }
5793 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005795 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005796 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005797 }
5798 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005799 confsect = CFG_USERLIST;
5800 free(cursection);
5801 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005802 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005803 else if (!strcmp(args[0], "peers")) {
5804 confsect = CFG_PEERS;
5805 free(cursection);
5806 cursection = strdup(args[0]);
5807 }
5808
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809 /* else it's a section keyword */
5810
5811 switch (confsect) {
5812 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005813 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814 break;
5815 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005816 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005818 case CFG_USERLIST:
5819 err_code |= cfg_parse_users(file, linenum, args, kwm);
5820 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005821 case CFG_PEERS:
5822 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5823 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005825 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005826 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005828
5829 if (err_code & ERR_ABORT)
5830 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005832 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005833 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005835 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005836}
5837
Willy Tarreaubb925012009-07-23 13:36:36 +02005838/*
5839 * Returns the error code, 0 if OK, or any combination of :
5840 * - ERR_ABORT: must abort ASAP
5841 * - ERR_FATAL: we can continue parsing but not start the service
5842 * - ERR_WARN: a warning has been emitted
5843 * - ERR_ALERT: an alert has been emitted
5844 * Only the two first ones can stop processing, the two others are just
5845 * indicators.
5846 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005847int check_config_validity()
5848{
5849 int cfgerr = 0;
5850 struct proxy *curproxy = NULL;
5851 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005852 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005853 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005854 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005855 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005856
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005857 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005858 /*
5859 * Now, check for the integrity of all that we have collected.
5860 */
5861
5862 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005863 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005864
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005865 /* first, we will invert the proxy list order */
5866 curproxy = NULL;
5867 while (proxy) {
5868 struct proxy *next;
5869
5870 next = proxy->next;
5871 proxy->next = curproxy;
5872 curproxy = proxy;
5873 if (!next)
5874 break;
5875 proxy = next;
5876 }
5877
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005879 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005880 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005881 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005882 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005883 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005884 unsigned int next_id;
5885
Willy Tarreau050536d2012-10-04 08:47:34 +02005886 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005887 /* proxy ID not set, use automatic numbering with first
5888 * spare entry starting with next_pxid.
5889 */
5890 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5891 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5892 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005893 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005894 next_pxid++;
5895
Willy Tarreau55ea7572007-06-17 19:56:27 +02005896
Willy Tarreaubaaee002006-06-26 02:48:02 +02005897 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005898 /* ensure we don't keep listeners uselessly bound */
5899 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005900 curproxy = curproxy->next;
5901 continue;
5902 }
5903
Willy Tarreauff01a212009-03-15 13:46:16 +01005904 switch (curproxy->mode) {
5905 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005906 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005907 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005908 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5909 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005910 cfgerr++;
5911 }
5912
5913 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005914 Warning("config : servers will be ignored for %s '%s'.\n",
5915 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005916 break;
5917
5918 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005919 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005920 break;
5921
5922 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005923 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005924 break;
5925 }
5926
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005927 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005928 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005929 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005930 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5931 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005932 cfgerr++;
5933 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005934#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005935 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005936 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5937 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005938 cfgerr++;
5939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005940#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005941 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005942 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5943 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005944 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005945 }
5946 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005947 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005948 /* If no LB algo is set in a backend, and we're not in
5949 * transparent mode, dispatch mode nor proxy mode, we
5950 * want to use balance roundrobin by default.
5951 */
5952 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5953 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005954 }
5955 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005956
Willy Tarreau1620ec32011-08-06 17:05:02 +02005957 if (curproxy->options & PR_O_DISPATCH)
5958 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5959 else if (curproxy->options & PR_O_HTTP_PROXY)
5960 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5961 else if (curproxy->options & PR_O_TRANSP)
5962 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005963
Willy Tarreau1620ec32011-08-06 17:05:02 +02005964 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5965 if (curproxy->options & PR_O_DISABLE404) {
5966 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5967 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5968 err_code |= ERR_WARN;
5969 curproxy->options &= ~PR_O_DISABLE404;
5970 }
5971 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5972 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5973 "send-state", proxy_type_str(curproxy), curproxy->id);
5974 err_code |= ERR_WARN;
5975 curproxy->options &= ~PR_O2_CHK_SNDST;
5976 }
Willy Tarreauef781042010-01-27 11:53:01 +01005977 }
5978
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005979 /* if a default backend was specified, let's find it */
5980 if (curproxy->defbe.name) {
5981 struct proxy *target;
5982
Alex Williams96532db2009-11-01 21:27:13 -05005983 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005984 if (!target) {
5985 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5986 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005987 cfgerr++;
5988 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005989 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5990 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005991 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005992 } else {
5993 free(curproxy->defbe.name);
5994 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005995 /* we force the backend to be present on at least all of
5996 * the frontend's processes.
5997 */
5998 target->bind_proc = curproxy->bind_proc ?
5999 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006000
6001 /* Emit a warning if this proxy also has some servers */
6002 if (curproxy->srv) {
6003 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6004 curproxy->id);
6005 err_code |= ERR_WARN;
6006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006007 }
6008 }
6009
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006010 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006011 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6012 /* map jump target for ACT_SETBE in req_rep chain */
6013 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006014 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006015 struct proxy *target;
6016
Willy Tarreaua496b602006-12-17 23:15:24 +01006017 if (exp->action != ACT_SETBE)
6018 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006019
Alex Williams96532db2009-11-01 21:27:13 -05006020 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006021 if (!target) {
6022 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6023 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006024 cfgerr++;
6025 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006026 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6027 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006028 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006029 } else {
6030 free((void *)exp->replace);
6031 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006032 /* we force the backend to be present on at least all of
6033 * the frontend's processes.
6034 */
6035 target->bind_proc = curproxy->bind_proc ?
6036 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006037 }
6038 }
6039 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006040
6041 /* find the target proxy for 'use_backend' rules */
6042 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006043 struct proxy *target;
6044
Alex Williams96532db2009-11-01 21:27:13 -05006045 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006046
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006047 if (!target) {
6048 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6049 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006050 cfgerr++;
6051 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006052 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6053 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006054 cfgerr++;
6055 } else {
6056 free((void *)rule->be.name);
6057 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006058 /* we force the backend to be present on at least all of
6059 * the frontend's processes.
6060 */
6061 target->bind_proc = curproxy->bind_proc ?
6062 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006063 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006064 }
6065
6066 /* find the target proxy for 'use_backend' rules */
6067 list_for_each_entry(srule, &curproxy->server_rules, list) {
6068 struct server *target = findserver(curproxy, srule->srv.name);
6069
6070 if (!target) {
6071 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6072 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6073 cfgerr++;
6074 continue;
6075 }
6076 free((void *)srule->srv.name);
6077 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006078 }
6079
Emeric Brunb982a3d2010-01-04 15:45:53 +01006080 /* find the target table for 'stick' rules */
6081 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6082 struct proxy *target;
6083
Emeric Brun1d33b292010-01-04 15:47:17 +01006084 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6085 if (mrule->flags & STK_IS_STORE)
6086 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6087
Emeric Brunb982a3d2010-01-04 15:45:53 +01006088 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006089 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006090 else
6091 target = curproxy;
6092
6093 if (!target) {
6094 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6095 curproxy->id, mrule->table.name);
6096 cfgerr++;
6097 }
6098 else if (target->table.size == 0) {
6099 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6100 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6101 cfgerr++;
6102 }
Willy Tarreau12785782012-04-27 21:37:17 +02006103 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6104 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006105 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6106 cfgerr++;
6107 }
6108 else {
6109 free((void *)mrule->table.name);
6110 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006111 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006112 }
6113 }
6114
6115 /* find the target table for 'store response' rules */
6116 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6117 struct proxy *target;
6118
Emeric Brun1d33b292010-01-04 15:47:17 +01006119 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6120
Emeric Brunb982a3d2010-01-04 15:45:53 +01006121 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006122 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006123 else
6124 target = curproxy;
6125
6126 if (!target) {
6127 Alert("Proxy '%s': unable to find store table '%s'.\n",
6128 curproxy->id, mrule->table.name);
6129 cfgerr++;
6130 }
6131 else if (target->table.size == 0) {
6132 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6133 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6134 cfgerr++;
6135 }
Willy Tarreau12785782012-04-27 21:37:17 +02006136 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6137 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006138 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6139 cfgerr++;
6140 }
6141 else {
6142 free((void *)mrule->table.name);
6143 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006144 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006145 }
6146 }
6147
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006148 /* find the target table for 'tcp-request' layer 4 rules */
6149 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6150 struct proxy *target;
6151
Willy Tarreau56123282010-08-06 19:06:56 +02006152 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006153 continue;
6154
6155 if (trule->act_prm.trk_ctr.table.n)
6156 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6157 else
6158 target = curproxy;
6159
6160 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006161 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6162 curproxy->id, trule->act_prm.trk_ctr.table.n,
6163 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006164 cfgerr++;
6165 }
6166 else if (target->table.size == 0) {
6167 Alert("Proxy '%s': table '%s' used but not configured.\n",
6168 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6169 cfgerr++;
6170 }
6171 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006172 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 +02006173 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6174 cfgerr++;
6175 }
6176 else {
6177 free(trule->act_prm.trk_ctr.table.n);
6178 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006179 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006180 * to pass a list of counters to track and allocate them right here using
6181 * stktable_alloc_data_type().
6182 */
6183 }
6184 }
6185
Willy Tarreaud1f96522010-08-03 19:34:32 +02006186 /* find the target table for 'tcp-request' layer 6 rules */
6187 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6188 struct proxy *target;
6189
Willy Tarreau56123282010-08-06 19:06:56 +02006190 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006191 continue;
6192
6193 if (trule->act_prm.trk_ctr.table.n)
6194 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6195 else
6196 target = curproxy;
6197
6198 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006199 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6200 curproxy->id, trule->act_prm.trk_ctr.table.n,
6201 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006202 cfgerr++;
6203 }
6204 else if (target->table.size == 0) {
6205 Alert("Proxy '%s': table '%s' used but not configured.\n",
6206 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6207 cfgerr++;
6208 }
6209 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006210 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 +02006211 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6212 cfgerr++;
6213 }
6214 else {
6215 free(trule->act_prm.trk_ctr.table.n);
6216 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006217 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006218 * to pass a list of counters to track and allocate them right here using
6219 * stktable_alloc_data_type().
6220 */
6221 }
6222 }
6223
Emeric Brun32da3c42010-09-23 18:39:19 +02006224 if (curproxy->table.peers.name) {
6225 struct peers *curpeers = peers;
6226
6227 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6228 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6229 free((void *)curproxy->table.peers.name);
6230 curproxy->table.peers.p = peers;
6231 break;
6232 }
6233 }
6234
6235 if (!curpeers) {
6236 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6237 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006238 free((void *)curproxy->table.peers.name);
6239 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006240 cfgerr++;
6241 }
6242 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006243 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6244 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006245 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006246 cfgerr++;
6247 }
6248 }
6249
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006250 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006251 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006252 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6253 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6254 "proxy", curproxy->id);
6255 cfgerr++;
6256 goto out_uri_auth_compat;
6257 }
6258
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006259 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006260 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006261 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006262 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006263
Willy Tarreau95fa4692010-02-01 13:05:50 +01006264 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6265 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006266
6267 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006268 uri_auth_compat_req[i++] = "realm";
6269 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6270 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006271
Willy Tarreau95fa4692010-02-01 13:05:50 +01006272 uri_auth_compat_req[i++] = "unless";
6273 uri_auth_compat_req[i++] = "{";
6274 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6275 uri_auth_compat_req[i++] = "}";
6276 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006277
Willy Tarreauff011f22011-01-06 17:51:27 +01006278 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6279 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006280 cfgerr++;
6281 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006282 }
6283
Willy Tarreauff011f22011-01-06 17:51:27 +01006284 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006285
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006286 if (curproxy->uri_auth->auth_realm) {
6287 free(curproxy->uri_auth->auth_realm);
6288 curproxy->uri_auth->auth_realm = NULL;
6289 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006290
6291 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006292 }
6293out_uri_auth_compat:
6294
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006295 cfgerr += acl_find_targets(curproxy);
6296
Willy Tarreau2738a142006-07-08 17:28:09 +02006297 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006298 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006299 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006300 (!curproxy->timeout.connect ||
6301 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006302 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006303 " | While not properly invalid, you will certainly encounter various problems\n"
6304 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006305 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006306 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006307 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006308 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006309
Willy Tarreau1fa31262007-12-03 00:36:16 +01006310 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6311 * We must still support older configurations, so let's find out whether those
6312 * parameters have been set or must be copied from contimeouts.
6313 */
6314 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006315 if (!curproxy->timeout.tarpit ||
6316 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006317 /* tarpit timeout not set. We search in the following order:
6318 * default.tarpit, curr.connect, default.connect.
6319 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006320 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006321 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006322 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006323 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006324 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006325 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006326 }
6327 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006328 (!curproxy->timeout.queue ||
6329 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006330 /* queue timeout not set. We search in the following order:
6331 * default.queue, curr.connect, default.connect.
6332 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006333 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006334 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006335 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006336 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006337 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006338 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006339 }
6340 }
6341
Willy Tarreau1620ec32011-08-06 17:05:02 +02006342 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006343 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6344 curproxy->check_req = (char *)malloc(curproxy->check_len);
6345 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006346 }
6347
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006348 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006349 if (curproxy->nb_req_cap) {
6350 if (curproxy->mode == PR_MODE_HTTP) {
6351 curproxy->req_cap_pool = create_pool("ptrcap",
6352 curproxy->nb_req_cap * sizeof(char *),
6353 MEM_F_SHARED);
6354 } else {
6355 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6356 proxy_type_str(curproxy), curproxy->id);
6357 err_code |= ERR_WARN;
6358 curproxy->to_log &= ~LW_REQHDR;
6359 curproxy->nb_req_cap = 0;
6360 }
6361 }
6362
6363 if (curproxy->nb_rsp_cap) {
6364 if (curproxy->mode == PR_MODE_HTTP) {
6365 curproxy->rsp_cap_pool = create_pool("ptrcap",
6366 curproxy->nb_rsp_cap * sizeof(char *),
6367 MEM_F_SHARED);
6368 } else {
6369 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6370 proxy_type_str(curproxy), curproxy->id);
6371 err_code |= ERR_WARN;
6372 curproxy->to_log &= ~LW_REQHDR;
6373 curproxy->nb_rsp_cap = 0;
6374 }
6375 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006376
Willy Tarreau196729e2012-05-31 19:30:26 +02006377 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006378 if (!(curproxy->cap & PR_CAP_FE)) {
6379 if (curproxy->logformat_string != default_http_log_format &&
6380 curproxy->logformat_string != default_tcp_log_format &&
6381 curproxy->logformat_string != clf_http_log_format)
6382 free(curproxy->logformat_string);
6383 curproxy->logformat_string = NULL;
6384 }
6385
Willy Tarreau196729e2012-05-31 19:30:26 +02006386 if (curproxy->logformat_string)
6387 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6388
6389 if (curproxy->uniqueid_format_string)
6390 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6391
Willy Tarreaubaaee002006-06-26 02:48:02 +02006392 /* first, we will invert the servers list order */
6393 newsrv = NULL;
6394 while (curproxy->srv) {
6395 struct server *next;
6396
6397 next = curproxy->srv->next;
6398 curproxy->srv->next = newsrv;
6399 newsrv = curproxy->srv;
6400 if (!next)
6401 break;
6402 curproxy->srv = next;
6403 }
6404
Willy Tarreaudd701652010-05-25 23:03:02 +02006405 /* assign automatic UIDs to servers which don't have one yet */
6406 next_id = 1;
6407 newsrv = curproxy->srv;
6408 while (newsrv != NULL) {
6409 if (!newsrv->puid) {
6410 /* server ID not set, use automatic numbering with first
6411 * spare entry starting with next_svid.
6412 */
6413 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6414 newsrv->conf.id.key = newsrv->puid = next_id;
6415 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6416 }
6417 next_id++;
6418 newsrv = newsrv->next;
6419 }
6420
Willy Tarreau20697042007-11-15 23:26:18 +01006421 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006422 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006423
Willy Tarreau62c3be22012-01-20 13:12:32 +01006424 /*
6425 * If this server supports a maxconn parameter, it needs a dedicated
6426 * tasks to fill the emptied slots when a connection leaves.
6427 * Also, resolve deferred tracking dependency if needed.
6428 */
6429 newsrv = curproxy->srv;
6430 while (newsrv != NULL) {
6431 if (newsrv->minconn > newsrv->maxconn) {
6432 /* Only 'minconn' was specified, or it was higher than or equal
6433 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6434 * this will avoid further useless expensive computations.
6435 */
6436 newsrv->maxconn = newsrv->minconn;
6437 } else if (newsrv->maxconn && !newsrv->minconn) {
6438 /* minconn was not specified, so we set it to maxconn */
6439 newsrv->minconn = newsrv->maxconn;
6440 }
6441
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006442#ifdef USE_OPENSSL
6443#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6444#define SSL_OP_NO_COMPRESSION 0
6445#endif
6446#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6447#define SSL_MODE_RELEASE_BUFFERS 0
6448#endif
6449#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6450#define SSL_OP_NO_COMPRESSION 0
6451#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +02006452#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
6453#define SSL_OP_NO_TLSv1_1 0
6454#endif
6455#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
6456#define SSL_OP_NO_TLSv1_2 0
6457#endif
Willy Tarreauf4288ee2012-09-28 18:13:10 +02006458 if (newsrv->use_ssl || newsrv->check.use_ssl) {
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006459 int ssloptions =
6460 SSL_OP_ALL | /* all known workarounds for bugs */
6461 SSL_OP_NO_SSLv2 |
6462 SSL_OP_NO_COMPRESSION;
6463 int sslmode =
6464 SSL_MODE_ENABLE_PARTIAL_WRITE |
6465 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6466 SSL_MODE_RELEASE_BUFFERS;
6467
6468 /* Initiate SSL context for current server */
6469 newsrv->ssl_ctx.reused_sess = NULL;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02006470 if (newsrv->use_ssl)
6471 newsrv->xprt = &ssl_sock;
Willy Tarreauf1503172012-09-28 19:39:36 +02006472 if (newsrv->check.use_ssl)
6473 newsrv->check.xprt = &ssl_sock;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006474 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6475 if(!newsrv->ssl_ctx.ctx) {
6476
6477 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6478 proxy_type_str(curproxy), curproxy->id,
6479 newsrv->id);
6480 cfgerr++;
6481 goto next_srv;
6482 }
6483
Emeric Brun89675492012-10-05 13:48:26 +02006484 if (newsrv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3)
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006485 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brun89675492012-10-05 13:48:26 +02006486 if (newsrv->ssl_ctx.options & SRV_SSL_O_NO_TLSV10)
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006487 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun89675492012-10-05 13:48:26 +02006488 if (newsrv->ssl_ctx.options & SRV_SSL_O_NO_TLSV11)
Emeric Brunc0ff4922012-09-28 19:37:02 +02006489 ssloptions |= SSL_OP_NO_TLSv1_1;
Emeric Brun89675492012-10-05 13:48:26 +02006490 if (newsrv->ssl_ctx.options & SRV_SSL_O_NO_TLSV12)
Emeric Brunc0ff4922012-09-28 19:37:02 +02006491 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun8694b9a2012-10-05 14:39:07 +02006492 if (newsrv->ssl_ctx.options & SRV_SSL_O_USE_SSLV3)
6493 SSL_CTX_set_ssl_version(newsrv->ssl_ctx.ctx, SSLv3_client_method());
6494 if (newsrv->ssl_ctx.options & SRV_SSL_O_USE_TLSV10)
6495 SSL_CTX_set_ssl_version(newsrv->ssl_ctx.ctx, TLSv1_client_method());
6496#if SSL_OP_NO_TLSv1_1
6497 if (newsrv->ssl_ctx.options & SRV_SSL_O_USE_TLSV11)
6498 SSL_CTX_set_ssl_version(newsrv->ssl_ctx.ctx, TLSv1_1_client_method());
6499#endif
6500#if SSL_OP_NO_TLSv1_2
6501 if (newsrv->ssl_ctx.options & SRV_SSL_O_USE_TLSV12)
6502 SSL_CTX_set_ssl_version(newsrv->ssl_ctx.ctx, TLSv1_2_client_method());
6503#endif
6504
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006505 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6506 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6507 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6508 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006509 if (newsrv->ssl_ctx.ciphers &&
6510 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6511 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6512 curproxy->id, newsrv->id,
6513 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6514 cfgerr++;
6515 goto next_srv;
6516 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006517 }
6518#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006519 if (newsrv->trackit) {
6520 struct proxy *px;
6521 struct server *srv;
6522 char *pname, *sname;
6523
6524 pname = newsrv->trackit;
6525 sname = strrchr(pname, '/');
6526
6527 if (sname)
6528 *sname++ = '\0';
6529 else {
6530 sname = pname;
6531 pname = NULL;
6532 }
6533
6534 if (pname) {
6535 px = findproxy(pname, PR_CAP_BE);
6536 if (!px) {
6537 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6538 proxy_type_str(curproxy), curproxy->id,
6539 newsrv->id, pname);
6540 cfgerr++;
6541 goto next_srv;
6542 }
6543 } else
6544 px = curproxy;
6545
6546 srv = findserver(px, sname);
6547 if (!srv) {
6548 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6549 proxy_type_str(curproxy), curproxy->id,
6550 newsrv->id, sname);
6551 cfgerr++;
6552 goto next_srv;
6553 }
6554
6555 if (!(srv->state & SRV_CHECKED)) {
6556 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6557 "tracking as it does not have checks enabled.\n",
6558 proxy_type_str(curproxy), curproxy->id,
6559 newsrv->id, px->id, srv->id);
6560 cfgerr++;
6561 goto next_srv;
6562 }
6563
6564 if (curproxy != px &&
6565 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6566 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6567 "tracking: disable-on-404 option inconsistency.\n",
6568 proxy_type_str(curproxy), curproxy->id,
6569 newsrv->id, px->id, srv->id);
6570 cfgerr++;
6571 goto next_srv;
6572 }
6573
6574 /* if the other server is forced disabled, we have to do the same here */
6575 if (srv->state & SRV_MAINTAIN) {
6576 newsrv->state |= SRV_MAINTAIN;
6577 newsrv->state &= ~SRV_RUNNING;
6578 newsrv->health = 0;
6579 }
6580
6581 newsrv->track = srv;
6582 newsrv->tracknext = srv->tracknext;
6583 srv->tracknext = newsrv;
6584
6585 free(newsrv->trackit);
6586 newsrv->trackit = NULL;
6587 }
6588 next_srv:
6589 newsrv = newsrv->next;
6590 }
6591
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006592 /* We have to initialize the server lookup mechanism depending
6593 * on what LB algorithm was choosen.
6594 */
6595
6596 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6597 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6598 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006599 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6600 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6601 init_server_map(curproxy);
6602 } else {
6603 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6604 fwrr_init_server_groups(curproxy);
6605 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006606 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006607
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006608 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006609 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6610 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6611 fwlc_init_server_tree(curproxy);
6612 } else {
6613 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6614 fas_init_server_tree(curproxy);
6615 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006616 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006617
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006618 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006619 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6620 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6621 chash_init_server_tree(curproxy);
6622 } else {
6623 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6624 init_server_map(curproxy);
6625 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006626 break;
6627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006628
6629 if (curproxy->options & PR_O_LOGASAP)
6630 curproxy->to_log &= ~LW_BYTES;
6631
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006632 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006633 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006634 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6635 proxy_type_str(curproxy), curproxy->id);
6636 err_code |= ERR_WARN;
6637 }
6638
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006639 if (curproxy->mode != PR_MODE_HTTP) {
6640 int optnum;
6641
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006642 if (curproxy->uri_auth) {
6643 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6644 proxy_type_str(curproxy), curproxy->id);
6645 err_code |= ERR_WARN;
6646 curproxy->uri_auth = NULL;
6647 }
6648
Willy Tarreau87cf5142011-08-19 22:57:24 +02006649 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006650 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6651 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6652 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006653 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006654 }
6655
6656 if (curproxy->options & PR_O_ORGTO) {
6657 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6658 "originalto", proxy_type_str(curproxy), curproxy->id);
6659 err_code |= ERR_WARN;
6660 curproxy->options &= ~PR_O_ORGTO;
6661 }
6662
6663 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6664 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6665 (curproxy->cap & cfg_opts[optnum].cap) &&
6666 (curproxy->options & cfg_opts[optnum].val)) {
6667 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6668 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6669 err_code |= ERR_WARN;
6670 curproxy->options &= ~cfg_opts[optnum].val;
6671 }
6672 }
6673
6674 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6675 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6676 (curproxy->cap & cfg_opts2[optnum].cap) &&
6677 (curproxy->options2 & cfg_opts2[optnum].val)) {
6678 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6679 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6680 err_code |= ERR_WARN;
6681 curproxy->options2 &= ~cfg_opts2[optnum].val;
6682 }
6683 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006684
Willy Tarreauefa5f512010-03-30 20:13:29 +02006685#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006686 if (curproxy->bind_hdr_occ) {
6687 curproxy->bind_hdr_occ = 0;
6688 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6689 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6690 err_code |= ERR_WARN;
6691 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006692#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006693 }
6694
Willy Tarreaubaaee002006-06-26 02:48:02 +02006695 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006696 * ensure that we're not cross-dressing a TCP server into HTTP.
6697 */
6698 newsrv = curproxy->srv;
6699 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006700 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006701 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6702 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006703 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006704 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006705
Willy Tarreau0cec3312011-10-31 13:49:26 +01006706 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6707 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6708 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6709 err_code |= ERR_WARN;
6710 }
6711
Willy Tarreauefa5f512010-03-30 20:13:29 +02006712#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006713 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6714 newsrv->bind_hdr_occ = 0;
6715 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6716 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6717 err_code |= ERR_WARN;
6718 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006719#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006720 newsrv = newsrv->next;
6721 }
6722
Willy Tarreauc1a21672009-08-16 22:37:44 +02006723 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006724 if (!curproxy->accept)
6725 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006726
Willy Tarreauc1a21672009-08-16 22:37:44 +02006727 if (curproxy->tcp_req.inspect_delay ||
6728 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006729 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006730
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006731 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006732 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006733 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006734 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006735
6736 /* both TCP and HTTP must check switching rules */
6737 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6738 }
6739
6740 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006741 if (curproxy->tcp_req.inspect_delay ||
6742 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6743 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6744
Emeric Brun97679e72010-09-23 17:56:44 +02006745 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6746 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6747
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006748 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006749 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006750 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006751 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006752
6753 /* If the backend does requires RDP cookie persistence, we have to
6754 * enable the corresponding analyser.
6755 */
6756 if (curproxy->options2 & PR_O2_RDPC_PRST)
6757 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6758 }
6759
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006760 /* Configure SSL for each bind line.
6761 * Note: if configuration fails at some point, the ->ctx member
6762 * remains NULL so that listeners can later detach.
6763 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006764 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6765 if (!bind_conf->is_ssl)
6766 continue;
6767#ifdef USE_OPENSSL
6768 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006769 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006770 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006771 cfgerr++;
6772 continue;
6773 }
6774
Emeric Brun4b3091e2012-09-24 15:48:52 +02006775 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006776 Alert("Unable to allocate SSL session cache.\n");
6777 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006778 continue;
6779 }
6780
Emeric Brunfc0421f2012-09-07 17:30:07 +02006781 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006782 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006783#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006784 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006785
Willy Tarreaue6b98942007-10-29 01:09:36 +01006786 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006787 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006788 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006789 if (!listener->luid) {
6790 /* listener ID not set, use automatic numbering with first
6791 * spare entry starting with next_luid.
6792 */
6793 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6794 listener->conf.id.key = listener->luid = next_id;
6795 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006796 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006797 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006798
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006799 /* enable separate counters */
6800 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6801 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6802 if (!listener->name) {
6803 sprintf(trash, "sock-%d", listener->luid);
6804 listener->name = strdup(trash);
6805 }
6806 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006807
Willy Tarreaue6b98942007-10-29 01:09:36 +01006808 if (curproxy->options & PR_O_TCP_NOLING)
6809 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006810 if (!listener->maxconn)
6811 listener->maxconn = curproxy->maxconn;
6812 if (!listener->backlog)
6813 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006814 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006815 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006816 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006817 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006818
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006819 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6820 listener->options |= LI_O_TCP_RULES;
6821
Willy Tarreaude3041d2010-05-31 10:56:17 +02006822 if (curproxy->mon_mask.s_addr)
6823 listener->options |= LI_O_CHK_MONNET;
6824
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006825 /* smart accept mode is automatic in HTTP mode */
6826 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006827 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006828 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6829 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006830 }
6831
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006832 /* Release unused SSL configs */
6833 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6834 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006835 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006836#ifdef USE_OPENSSL
6837 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006838 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006839 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006840 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006841 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006842#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006843 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006844
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006845 /* Check multi-process mode compatibility for the current proxy */
6846 if (global.nbproc > 1) {
6847 int nbproc = 0;
6848 if (curproxy->bind_proc) {
6849 int proc;
6850 for (proc = 0; proc < global.nbproc; proc++) {
6851 if (curproxy->bind_proc & (1 << proc)) {
6852 nbproc++;
6853 }
6854 }
6855 } else {
6856 nbproc = global.nbproc;
6857 }
6858 if (curproxy->table.peers.name) {
6859 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6860 curproxy->id);
6861 cfgerr++;
6862 }
6863 if (nbproc > 1) {
6864 if (curproxy->uri_auth) {
6865 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6866 curproxy->id);
6867 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6868 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6869 curproxy->id);
6870 }
6871 }
6872 if (curproxy->appsession_name) {
6873 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6874 curproxy->id);
6875 }
6876 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6877 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6878 curproxy->id);
6879 }
6880 }
6881 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006882
6883 /* create the task associated with the proxy */
6884 curproxy->task = task_new();
6885 if (curproxy->task) {
6886 curproxy->task->context = curproxy;
6887 curproxy->task->process = manage_proxy;
6888 /* no need to queue, it will be done automatically if some
6889 * listener gets limited.
6890 */
6891 curproxy->task->expire = TICK_ETERNITY;
6892 } else {
6893 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6894 curproxy->id);
6895 cfgerr++;
6896 }
6897
Willy Tarreaubaaee002006-06-26 02:48:02 +02006898 curproxy = curproxy->next;
6899 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006900
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006901 /* Check multi-process mode compatibility */
6902 if (global.nbproc > 1) {
6903 if (global.stats_fe) {
6904 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6905 }
6906 }
6907
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006908 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6909 struct auth_users *curuser;
6910 int g;
6911
6912 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6913 unsigned int group_mask = 0;
6914 char *group = NULL;
6915
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006916 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006917 continue;
6918
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006919 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006920
6921 for (g = 0; g < curuserlist->grpcnt; g++)
6922 if (!strcmp(curuserlist->groups[g], group))
6923 break;
6924
6925 if (g == curuserlist->grpcnt) {
6926 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6927 curuserlist->name, group, curuser->user);
6928 err_code |= ERR_ALERT | ERR_FATAL;
6929 goto out;
6930 }
6931
6932 group_mask |= (1 << g);
6933 }
6934
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006935 free(curuser->u.groups);
6936 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006937 }
6938
6939 for (g = 0; g < curuserlist->grpcnt; g++) {
6940 char *user = NULL;
6941
6942 if (!curuserlist->groupusers[g])
6943 continue;
6944
6945 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6946 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6947 if (!strcmp(curuser->user, user))
6948 break;
6949
6950 if (!curuser) {
6951 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6952 curuserlist->name, user, curuserlist->groups[g]);
6953 err_code |= ERR_ALERT | ERR_FATAL;
6954 goto out;
6955 }
6956
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006957 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006958 }
6959
6960 free(curuserlist->groupusers[g]);
6961 }
6962
6963 free(curuserlist->groupusers);
6964
6965#ifdef DEBUG_AUTH
6966 for (g = 0; g < curuserlist->grpcnt; g++) {
6967 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6968
6969 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006970 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006971 fprintf(stderr, " %s", curuser->user);
6972 }
6973
6974 fprintf(stderr, "\n");
6975 }
6976#endif
6977
Willy Tarreaufbb78422011-06-05 15:38:35 +02006978 }
6979
6980 /* automatically compute fullconn if not set. We must not do it in the
6981 * loop above because cross-references are not yet fully resolved.
6982 */
6983 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6984 /* If <fullconn> is not set, let's set it to 10% of the sum of
6985 * the possible incoming frontend's maxconns.
6986 */
6987 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6988 struct proxy *fe;
6989 int total = 0;
6990
6991 /* sum up the number of maxconns of frontends which
6992 * reference this backend at least once or which are
6993 * the same one ('listen').
6994 */
6995 for (fe = proxy; fe; fe = fe->next) {
6996 struct switching_rule *rule;
6997 struct hdr_exp *exp;
6998 int found = 0;
6999
7000 if (!(fe->cap & PR_CAP_FE))
7001 continue;
7002
7003 if (fe == curproxy) /* we're on a "listen" instance */
7004 found = 1;
7005
7006 if (fe->defbe.be == curproxy) /* "default_backend" */
7007 found = 1;
7008
7009 /* check if a "use_backend" rule matches */
7010 if (!found) {
7011 list_for_each_entry(rule, &fe->switching_rules, list) {
7012 if (rule->be.backend == curproxy) {
7013 found = 1;
7014 break;
7015 }
7016 }
7017 }
7018
7019 /* check if a "reqsetbe" rule matches */
7020 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7021 if (exp->action == ACT_SETBE &&
7022 (struct proxy *)exp->replace == curproxy) {
7023 found = 1;
7024 break;
7025 }
7026 }
7027
7028 /* now we've checked all possible ways to reference a backend
7029 * from a frontend.
7030 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007031 if (!found)
7032 continue;
7033 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007034 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007035 /* we have the sum of the maxconns in <total>. We only
7036 * keep 10% of that sum to set the default fullconn, with
7037 * a hard minimum of 1 (to avoid a divide by zero).
7038 */
7039 curproxy->fullconn = (total + 9) / 10;
7040 if (!curproxy->fullconn)
7041 curproxy->fullconn = 1;
7042 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007043 }
7044
Willy Tarreau056f5682010-06-06 15:51:11 +02007045 /* initialize stick-tables on backend capable proxies. This must not
7046 * be done earlier because the data size may be discovered while parsing
7047 * other proxies.
7048 */
7049 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007050 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007051
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007052 /*
7053 * Recount currently required checks.
7054 */
7055
7056 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7057 int optnum;
7058
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007059 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7060 if (curproxy->options & cfg_opts[optnum].val)
7061 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007062
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007063 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7064 if (curproxy->options2 & cfg_opts2[optnum].val)
7065 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007066 }
7067
Willy Tarreau122541c2011-09-07 21:24:49 +02007068 if (peers) {
7069 struct peers *curpeers = peers, **last;
7070 struct peer *p, *pb;
7071
7072 /* Remove all peers sections which don't have a valid listener.
7073 * This can happen when a peers section is never referenced and
7074 * does not contain a local peer.
7075 */
7076 last = &peers;
7077 while (*last) {
7078 curpeers = *last;
7079 if (curpeers->peers_fe) {
7080 last = &curpeers->next;
7081 continue;
7082 }
7083
7084 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7085 curpeers->id, localpeer);
7086
7087 p = curpeers->remote;
7088 while (p) {
7089 pb = p->next;
7090 free(p->id);
7091 free(p);
7092 p = pb;
7093 }
7094
7095 /* Destroy and unlink this curpeers section.
7096 * Note: curpeers is backed up into *last.
7097 */
7098 free(curpeers->id);
7099 curpeers = curpeers->next;
7100 free(*last);
7101 *last = curpeers;
7102 }
7103 }
7104
Willy Tarreauac1932d2011-10-24 19:14:41 +02007105 if (!global.tune.max_http_hdr)
7106 global.tune.max_http_hdr = MAX_HTTP_HDR;
7107
Willy Tarreau34eb6712011-10-24 18:15:04 +02007108 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007109 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007110 MEM_F_SHARED);
7111
Willy Tarreaubb925012009-07-23 13:36:36 +02007112 if (cfgerr > 0)
7113 err_code |= ERR_ALERT | ERR_FATAL;
7114 out:
7115 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007116}
7117
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007118/*
7119 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7120 * parsing sessions.
7121 */
7122void cfg_register_keywords(struct cfg_kw_list *kwl)
7123{
7124 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7125}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007126
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007127/*
7128 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7129 */
7130void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7131{
7132 LIST_DEL(&kwl->list);
7133 LIST_INIT(&kwl->list);
7134}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007135
7136/*
7137 * Local variables:
7138 * c-indent-level: 8
7139 * c-basic-offset: 8
7140 * End:
7141 */