blob: 9d1a6fd14e426fba6e1b54693e6b1f63cb08576b [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
36#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020037#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020042#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020045#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020046#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010048#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020052#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020061#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010063#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020064#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010066#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
Emeric Brunfc0421f2012-09-07 17:30:07 +020068#ifdef USE_OPENSSL
69#include <types/ssl_sock.h>
70#include <proto/ssl_sock.h>
71#include <proto/shctx.h>
72#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020073
Willy Tarreauf3c69202006-07-09 16:42:34 +020074/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
75 * ssl-hello-chk option to ensure that the remote server speaks SSL.
76 *
77 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
78 */
79const char sslv3_client_hello_pkt[] = {
80 "\x16" /* ContentType : 0x16 = Hanshake */
81 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
82 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
83 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
84 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
85 "\x03\x00" /* Hello Version : 0x0300 = v3 */
86 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
87 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
88 "\x00" /* Session ID length : empty (no session ID) */
89 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
90 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
91 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
92 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
93 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
94 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
95 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
96 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
97 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
98 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
99 "\x00\x38" "\x00\x39" "\x00\x3A"
100 "\x01" /* Compression Length : 0x01 = 1 byte for types */
101 "\x00" /* Compression Type : 0x00 = NULL compression */
102};
103
Willy Tarreau3842f002009-06-14 11:39:52 +0200104/* various keyword modifiers */
105enum kw_mod {
106 KWM_STD = 0, /* normal */
107 KWM_NO, /* "no" prefixed before the keyword */
108 KWM_DEF, /* "default" prefixed before the keyword */
109};
110
Willy Tarreau13943ab2006-12-31 00:24:10 +0100111/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113 const char *name;
114 unsigned int val;
115 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100116 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118};
119
120/* proxy->options */
121static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100122{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100123 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
124 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
125 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
127 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
128 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
129 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
130 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
131 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
133 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200193 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
194 * not NULL, it must be a valid pointer to either NULL or a freeable area that
195 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200197int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198{
199 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100200 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 int port, end;
202
203 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200204
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 while (next && *next) {
206 struct sockaddr_storage ss;
207
208 str = next;
209 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100210 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211 *next++ = 0;
212 }
213
Emeric Bruned760922010-10-22 17:59:25 +0200214 if (*str == '/') {
215 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
216 /* so compute max path */
217 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
218 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
Emeric Bruned760922010-10-22 17:59:25 +0200220 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200221 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200222 goto fail;
223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200226 ss.ss_family = AF_UNIX;
227 if (global.unix_bind.prefix) {
228 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
229 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 }
Emeric Bruned760922010-10-22 17:59:25 +0200231 else {
232 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
233 }
234 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 }
236 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100237 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100239 ss2 = str2sa_range(str, &port, &end);
240 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200241 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 if (!port) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200246 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 /* OK the address looks correct */
251 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
263
264 for (; port <= end; port++) {
265 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau4348fad2012-09-20 16:48:07 +0200266 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
267 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
268 l->frontend = curproxy;
269 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
271 l->fd = -1;
272 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200273 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100274 l->state = LI_INIT;
275
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100276 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 tcpv4_add_listener(l);
279 }
Emeric Bruned760922010-10-22 17:59:25 +0200280 else if (ss.ss_family == AF_INET6) {
281 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
282 tcpv6_add_listener(l);
283 }
284 else {
Emeric Bruned760922010-10-22 17:59:25 +0200285 uxst_add_listener(l);
286 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200288 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 } /* end for(port) */
291 } /* end while(next) */
292 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200293 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 fail:
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297}
298
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299/*
300 * Sends a warning if proxy <proxy> does not have at least one of the
301 * capabilities in <cap>. An optionnal <hint> may be added at the end
302 * of the warning to help the user. Returns 1 if a warning was emitted
303 * or 0 if the condition is valid.
304 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100305int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100306{
307 char *msg;
308
309 switch (cap) {
310 case PR_CAP_BE: msg = "no backend"; break;
311 case PR_CAP_FE: msg = "no frontend"; break;
312 case PR_CAP_RS: msg = "no ruleset"; break;
313 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
314 default: msg = "not enough"; break;
315 }
316
317 if (!(proxy->cap & cap)) {
318 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100319 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320 return 1;
321 }
322 return 0;
323}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324
Willy Tarreau61d18892009-03-31 10:49:21 +0200325/* Report a warning if a rule is placed after a 'block' rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100328int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200329{
330 if (!LIST_ISEMPTY(&proxy->block_cond)) {
331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
338/* Report a warning if a rule is placed after a reqrewrite rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100341int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200342{
343 if (proxy->req_exp) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a reqadd rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100354int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200355{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100356 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* Report a warning if a rule is placed after a redirect rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100367int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200368{
369 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
377/* Report a warning if a rule is placed after a 'use_backend' rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
382 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
390/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100391int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200392{
393 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
394 warnif_rule_after_reqadd(proxy, file, line, arg) ||
395 warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
399/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
403 warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
407/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100408int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200409{
410 return warnif_rule_after_redirect(proxy, file, line, arg) ||
411 warnif_rule_after_use_backend(proxy, file, line, arg);
412}
413
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100414/* Report it if a request ACL condition uses some response-only parameters. It
415 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
416 * Note that <cond> may be NULL and then will be ignored.
417 */
418static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
419{
420 struct acl *acl;
421
422 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
423 return 0;
424
425 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
426 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
427 file, line, acl ? acl->name : "(unknown)");
428 return ERR_WARN;
429}
430
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100431/* Report it if a request ACL condition uses some request-only volatile parameters.
432 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
433 * Note that <cond> may be NULL and then will be ignored.
434 */
435static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
436{
437 struct acl *acl;
438
439 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
440 return 0;
441
442 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
443 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
444 file, line, acl ? acl->name : "(unknown)");
445 return ERR_WARN;
446}
447
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100448
Willy Tarreaubaaee002006-06-26 02:48:02 +0200449/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 * parse a line in a <global> section. Returns the error code, 0 if OK, or
451 * any combination of :
452 * - ERR_ABORT: must abort ASAP
453 * - ERR_FATAL: we can continue parsing but not start the service
454 * - ERR_WARN: a warning has been emitted
455 * - ERR_ALERT: an alert has been emitted
456 * Only the two first ones can stop processing, the two others are just
457 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200459int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460{
Willy Tarreau058e9072009-07-20 09:30:05 +0200461 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200462 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463
464 if (!strcmp(args[0], "global")) { /* new section */
465 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 }
468 else if (!strcmp(args[0], "daemon")) {
469 global.mode |= MODE_DAEMON;
470 }
471 else if (!strcmp(args[0], "debug")) {
472 global.mode |= MODE_DEBUG;
473 }
474 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100475 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200477 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200479 }
480 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100481 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100484 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100486 else if (!strcmp(args[0], "nosplice")) {
487 global.tune.options &= ~GTUNE_USE_SPLICE;
488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200489 else if (!strcmp(args[0], "quiet")) {
490 global.mode |= MODE_QUIET;
491 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200492 else if (!strcmp(args[0], "tune.maxpollevents")) {
493 if (global.tune.maxpollevents != 0) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200495 err_code |= ERR_ALERT;
496 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200502 }
503 global.tune.maxpollevents = atol(args[1]);
504 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100505 else if (!strcmp(args[0], "tune.maxaccept")) {
506 if (global.tune.maxaccept != 0) {
507 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200508 err_code |= ERR_ALERT;
509 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100510 }
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100515 }
516 global.tune.maxaccept = atol(args[1]);
517 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200518 else if (!strcmp(args[0], "tune.chksize")) {
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.tune.chksize = atol(args[1]);
525 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200526#ifdef USE_OPENSSL
527 else if (!strcmp(args[0], "tune.sslcachesize")) {
528 if (*(args[1]) == 0) {
529 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
530 err_code |= ERR_ALERT | ERR_FATAL;
531 goto out;
532 }
533 global.tune.sslcachesize = atol(args[1]);
534 }
535#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200536 else if (!strcmp(args[0], "tune.bufsize")) {
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
541 }
542 global.tune.bufsize = atol(args[1]);
543 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
544 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200545 trashlen = global.tune.bufsize;
546 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200547 }
548 else if (!strcmp(args[0], "tune.maxrewrite")) {
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
553 }
554 global.tune.maxrewrite = atol(args[1]);
555 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
556 global.tune.maxrewrite = global.tune.bufsize / 2;
557 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100558 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
559 if (global.tune.client_rcvbuf != 0) {
560 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT;
562 goto out;
563 }
564 if (*(args[1]) == 0) {
565 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT | ERR_FATAL;
567 goto out;
568 }
569 global.tune.client_rcvbuf = atol(args[1]);
570 }
571 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
572 if (global.tune.server_rcvbuf != 0) {
573 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT;
575 goto out;
576 }
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582 global.tune.server_rcvbuf = atol(args[1]);
583 }
584 else if (!strcmp(args[0], "tune.sndbuf.client")) {
585 if (global.tune.client_sndbuf != 0) {
586 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT;
588 goto out;
589 }
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT | ERR_FATAL;
593 goto out;
594 }
595 global.tune.client_sndbuf = atol(args[1]);
596 }
597 else if (!strcmp(args[0], "tune.sndbuf.server")) {
598 if (global.tune.server_sndbuf != 0) {
599 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT;
601 goto out;
602 }
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.server_sndbuf = atol(args[1]);
609 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200610 else if (!strcmp(args[0], "tune.pipesize")) {
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.pipesize = atol(args[1]);
617 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200618 else if (!strcmp(args[0], "tune.http.maxhdr")) {
619 if (*(args[1]) == 0) {
620 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
621 err_code |= ERR_ALERT | ERR_FATAL;
622 goto out;
623 }
624 global.tune.max_http_hdr = atol(args[1]);
625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 else if (!strcmp(args[0], "uid")) {
627 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200628 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT;
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 }
632 if (*(args[1]) == 0) {
633 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT | ERR_FATAL;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 global.uid = atol(args[1]);
638 }
639 else if (!strcmp(args[0], "gid")) {
640 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200641 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200642 err_code |= ERR_ALERT;
643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
645 if (*(args[1]) == 0) {
646 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200647 err_code |= ERR_ALERT | ERR_FATAL;
648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649 }
650 global.gid = atol(args[1]);
651 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200652 /* user/group name handling */
653 else if (!strcmp(args[0], "user")) {
654 struct passwd *ha_user;
655 if (global.uid != 0) {
656 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200657 err_code |= ERR_ALERT;
658 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200659 }
660 errno = 0;
661 ha_user = getpwnam(args[1]);
662 if (ha_user != NULL) {
663 global.uid = (int)ha_user->pw_uid;
664 }
665 else {
666 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200667 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 }
670 else if (!strcmp(args[0], "group")) {
671 struct group *ha_group;
672 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200673 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200674 err_code |= ERR_ALERT;
675 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200676 }
677 errno = 0;
678 ha_group = getgrnam(args[1]);
679 if (ha_group != NULL) {
680 global.gid = (int)ha_group->gr_gid;
681 }
682 else {
683 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200684 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200685 }
686 }
687 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 else if (!strcmp(args[0], "nbproc")) {
689 if (global.nbproc != 0) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.nbproc = atol(args[1]);
700 }
701 else if (!strcmp(args[0], "maxconn")) {
702 if (global.maxconn != 0) {
703 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200704 err_code |= ERR_ALERT;
705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200706 }
707 if (*(args[1]) == 0) {
708 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 }
712 global.maxconn = atol(args[1]);
713#ifdef SYSTEM_MAXCONN
714 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
715 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
716 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200717 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200718 }
719#endif /* SYSTEM_MAXCONN */
720 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200721 else if (!strcmp(args[0], "maxsslconn")) {
722#ifdef USE_OPENSSL
723 if (*(args[1]) == 0) {
724 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
725 err_code |= ERR_ALERT | ERR_FATAL;
726 goto out;
727 }
728 global.maxsslconn = atol(args[1]);
729#else
Emeric Brun0914df82012-10-02 18:45:42 +0200730 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200733#endif
734 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200735 else if (!strcmp(args[0], "maxconnrate")) {
736 if (global.cps_lim != 0) {
737 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
738 err_code |= ERR_ALERT;
739 goto out;
740 }
741 if (*(args[1]) == 0) {
742 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
745 }
746 global.cps_lim = atol(args[1]);
747 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100748 else if (!strcmp(args[0], "maxpipes")) {
749 if (global.maxpipes != 0) {
750 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200751 err_code |= ERR_ALERT;
752 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100753 }
754 if (*(args[1]) == 0) {
755 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100758 }
759 global.maxpipes = atol(args[1]);
760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200761 else if (!strcmp(args[0], "ulimit-n")) {
762 if (global.rlimit_nofile != 0) {
763 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200764 err_code |= ERR_ALERT;
765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766 }
767 if (*(args[1]) == 0) {
768 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 }
772 global.rlimit_nofile = atol(args[1]);
773 }
774 else if (!strcmp(args[0], "chroot")) {
775 if (global.chroot != NULL) {
776 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200777 err_code |= ERR_ALERT;
778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 }
780 if (*(args[1]) == 0) {
781 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 global.chroot = strdup(args[1]);
786 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200787 else if (!strcmp(args[0], "description")) {
788 int i, len=0;
789 char *d;
790
791 if (!*args[1]) {
792 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
793 file, linenum, args[0]);
794 err_code |= ERR_ALERT | ERR_FATAL;
795 goto out;
796 }
797
798 for(i=1; *args[i]; i++)
799 len += strlen(args[i])+1;
800
801 if (global.desc)
802 free(global.desc);
803
804 global.desc = d = (char *)calloc(1, len);
805
806 d += sprintf(d, "%s", args[1]);
807 for(i=2; *args[i]; i++)
808 d += sprintf(d, " %s", args[i]);
809 }
810 else if (!strcmp(args[0], "node")) {
811 int i;
812 char c;
813
814 for (i=0; args[1][i]; i++) {
815 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100816 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
817 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200818 break;
819 }
820
821 if (!i || args[1][i]) {
822 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
823 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
824 file, linenum, args[0]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828
829 if (global.node)
830 free(global.node);
831
832 global.node = strdup(args[1]);
833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 else if (!strcmp(args[0], "pidfile")) {
835 if (global.pidfile != NULL) {
836 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT;
838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840 if (*(args[1]) == 0) {
841 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200842 err_code |= ERR_ALERT | ERR_FATAL;
843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 }
845 global.pidfile = strdup(args[1]);
846 }
Emeric Bruned760922010-10-22 17:59:25 +0200847 else if (!strcmp(args[0], "unix-bind")) {
848 int cur_arg = 1;
849 while (*(args[cur_arg])) {
850 if (!strcmp(args[cur_arg], "prefix")) {
851 if (global.unix_bind.prefix != NULL) {
852 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
853 err_code |= ERR_ALERT;
854 cur_arg += 2;
855 continue;
856 }
857
858 if (*(args[cur_arg+1]) == 0) {
859 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 global.unix_bind.prefix = strdup(args[cur_arg+1]);
864 cur_arg += 2;
865 continue;
866 }
867
868 if (!strcmp(args[cur_arg], "mode")) {
869
870 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
871 cur_arg += 2;
872 continue;
873 }
874
875 if (!strcmp(args[cur_arg], "uid")) {
876
877 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
878 cur_arg += 2;
879 continue;
880 }
881
882 if (!strcmp(args[cur_arg], "gid")) {
883
884 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
885 cur_arg += 2;
886 continue;
887 }
888
889 if (!strcmp(args[cur_arg], "user")) {
890 struct passwd *user;
891
892 user = getpwnam(args[cur_arg + 1]);
893 if (!user) {
894 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
895 file, linenum, args[0], args[cur_arg + 1 ]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899
900 global.unix_bind.ux.uid = user->pw_uid;
901 cur_arg += 2;
902 continue;
903 }
904
905 if (!strcmp(args[cur_arg], "group")) {
906 struct group *group;
907
908 group = getgrnam(args[cur_arg + 1]);
909 if (!group) {
910 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
911 file, linenum, args[0], args[cur_arg + 1 ]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914 }
915
916 global.unix_bind.ux.gid = group->gr_gid;
917 cur_arg += 2;
918 continue;
919 }
920
Willy Tarreaub48f9582011-09-05 01:17:06 +0200921 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200922 file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
926 }
William Lallemand0f99e342011-10-12 17:50:54 +0200927 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
928 /* delete previous herited or defined syslog servers */
929 struct logsrv *back;
930 struct logsrv *tmp;
931
932 if (*(args[1]) != 0) {
933 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937
938 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
939 LIST_DEL(&tmp->list);
940 free(tmp);
941 }
942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200944 struct logsrv *logsrv;
945
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 if (*(args[1]) == 0 || *(args[2]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 }
William Lallemand0f99e342011-10-12 17:50:54 +0200951
952 logsrv = calloc(1, sizeof(struct logsrv));
953
954 logsrv->facility = get_log_facility(args[2]);
955 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200957 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200958 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 }
960
William Lallemand0f99e342011-10-12 17:50:54 +0200961 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200963 logsrv->level = get_log_level(args[3]);
964 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200967 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 }
970
William Lallemand0f99e342011-10-12 17:50:54 +0200971 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200972 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200973 logsrv->minlvl = get_log_level(args[4]);
974 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200975 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200976 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200977 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200978 }
979 }
980
Robert Tsai81ae1952007-12-05 10:47:29 +0100981 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100982 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100983 if (!sk) {
984 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100985 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100986 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200987 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100988 goto out;
989 }
William Lallemand0f99e342011-10-12 17:50:54 +0200990 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100991 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100992 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100993 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100994 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
995 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200996 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100997 goto out;
998 }
William Lallemand0f99e342011-10-12 17:50:54 +0200999 logsrv->addr = *sk;
1000 if (!get_host_port(&logsrv->addr))
1001 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003
William Lallemand0f99e342011-10-12 17:50:54 +02001004 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001005 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001006 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1007 char *name;
1008 int len;
1009
1010 if (global.log_send_hostname != NULL) {
1011 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1012 err_code |= ERR_ALERT;
1013 goto out;
1014 }
1015
1016 if (*(args[1]))
1017 name = args[1];
1018 else
1019 name = hostname;
1020
1021 len = strlen(name);
1022
1023 /* We'll add a space after the name to respect the log format */
1024 free(global.log_send_hostname);
1025 global.log_send_hostname = malloc(len + 2);
1026 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1027 }
Kevinm48936af2010-12-22 16:08:21 +00001028 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1029 if (*(args[1]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033 }
1034 free(global.log_tag);
1035 global.log_tag = strdup(args[1]);
1036 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001037 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1038 if (global.spread_checks != 0) {
1039 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT;
1041 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001042 }
1043 if (*(args[1]) == 0) {
1044 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001047 }
1048 global.spread_checks = atol(args[1]);
1049 if (global.spread_checks < 0 || global.spread_checks > 50) {
1050 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001051 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 }
1054 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001055 struct cfg_kw_list *kwl;
1056 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001057 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001058
1059 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1060 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1061 if (kwl->kw[index].section != CFG_GLOBAL)
1062 continue;
1063 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1064 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001065 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001066 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau28a47d62012-09-18 20:02:48 +02001067 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001068 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001069 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001070 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001071 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001072 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001073 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001074 err_code |= ERR_WARN;
1075 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001076 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001077 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001078 }
1079 }
1080 }
1081
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001083 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001085
Willy Tarreau058e9072009-07-20 09:30:05 +02001086 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001087 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089}
1090
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001091void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001093 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 defproxy.mode = PR_MODE_TCP;
1095 defproxy.state = PR_STNEW;
1096 defproxy.maxconn = cfg_maxpconn;
1097 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001098
1099 defproxy.defsrv.inter = DEF_CHKINTR;
1100 defproxy.defsrv.fastinter = 0;
1101 defproxy.defsrv.downinter = 0;
1102 defproxy.defsrv.rise = DEF_RISETIME;
1103 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001104 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001105 defproxy.defsrv.maxqueue = 0;
1106 defproxy.defsrv.minconn = 0;
1107 defproxy.defsrv.maxconn = 0;
1108 defproxy.defsrv.slowstart = 0;
1109 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1110 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1111 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001112}
1113
Willy Tarreauade5ec42010-01-28 19:33:49 +01001114
1115static int create_cond_regex_rule(const char *file, int line,
1116 struct proxy *px, int dir, int action, int flags,
1117 const char *cmd, const char *reg, const char *repl,
1118 const char **cond_start)
1119{
1120 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001121 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001122 const char *err;
1123 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001124 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001125
1126 if (px == &defproxy) {
1127 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto err;
1130 }
1131
1132 if (*reg == 0) {
1133 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1134 err_code |= ERR_ALERT | ERR_FATAL;
1135 goto err;
1136 }
1137
1138 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1139 err_code |= ERR_WARN;
1140
Willy Tarreau5321c422010-01-28 20:35:13 +01001141 if (cond_start &&
1142 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001143 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1144 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1145 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001146 err_code |= ERR_ALERT | ERR_FATAL;
1147 goto err;
1148 }
1149 }
1150 else if (cond_start && **cond_start) {
1151 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1152 file, line, cmd, *cond_start);
1153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto err;
1155 }
1156
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001157 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001158 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001159 else
1160 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001161
Willy Tarreauade5ec42010-01-28 19:33:49 +01001162 preg = calloc(1, sizeof(regex_t));
1163 if (!preg) {
1164 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1165 err_code = ERR_ALERT | ERR_FATAL;
1166 goto err;
1167 }
1168
1169 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1170 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1171 err_code = ERR_ALERT | ERR_FATAL;
1172 goto err;
1173 }
1174
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001175 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001176 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001177 if (repl && err) {
1178 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1179 file, line, cmd, *err);
1180 err_code |= ERR_ALERT | ERR_FATAL;
1181 goto err;
1182 }
1183
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001184 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001185 err_code |= ERR_WARN;
1186
Willy Tarreauf4068b62012-05-08 17:37:49 +02001187 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001188 return err_code;
1189 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001190 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001191 free(preg);
1192 return err_code;
1193}
1194
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001196 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001197 * Returns the error code, 0 if OK, or any combination of :
1198 * - ERR_ABORT: must abort ASAP
1199 * - ERR_FATAL: we can continue parsing but not start the service
1200 * - ERR_WARN: a warning has been emitted
1201 * - ERR_ALERT: an alert has been emitted
1202 * Only the two first ones can stop processing, the two others are just
1203 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001205int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1206{
1207 static struct peers *curpeers = NULL;
1208 struct peer *newpeer = NULL;
1209 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001210 struct bind_conf *bind_conf;
1211 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001212 int err_code = 0;
1213
1214 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1215
1216 err = invalid_char(args[1]);
1217 if (err) {
1218 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1219 file, linenum, *err, args[0], args[1]);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 }
1222
1223 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1224 /*
1225 * If there are two proxies with the same name only following
1226 * combinations are allowed:
1227 */
1228 if (strcmp(curpeers->id, args[1]) == 0) {
1229 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1230 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1231 err_code |= ERR_WARN;
1232 }
1233 }
1234
1235 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1236 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1237 err_code |= ERR_ALERT | ERR_ABORT;
1238 goto out;
1239 }
1240
1241 curpeers->next = peers;
1242 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001243 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001244 curpeers->conf.line = linenum;
1245 curpeers->last_change = now.tv_sec;
1246 curpeers->id = strdup(args[1]);
1247 }
1248 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1249 char *rport, *raddr;
1250 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001251 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001252 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001253
1254 if (!*args[2]) {
1255 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1256 file, linenum, args[0]);
1257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
1259 }
1260
1261 err = invalid_char(args[1]);
1262 if (err) {
1263 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1264 file, linenum, *err, args[1]);
1265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
1267 }
1268
1269 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1270 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1271 err_code |= ERR_ALERT | ERR_ABORT;
1272 goto out;
1273 }
1274
1275 /* the peers are linked backwards first */
1276 curpeers->count++;
1277 newpeer->next = curpeers->remote;
1278 curpeers->remote = newpeer;
1279 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001280 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001281 newpeer->conf.line = linenum;
1282
1283 newpeer->last_change = now.tv_sec;
1284 newpeer->id = strdup(args[1]);
1285
1286 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001287 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001288 if (rport) {
1289 *rport++ = 0;
1290 realport = atol(rport);
1291 }
1292 if (!realport) {
1293 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1294 err_code |= ERR_ALERT | ERR_FATAL;
1295 goto out;
1296 }
1297
Willy Tarreaufab5a432011-03-04 15:31:53 +01001298 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001299 free(raddr);
1300 if (!sk) {
1301 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1302 err_code |= ERR_ALERT | ERR_FATAL;
1303 goto out;
1304 }
1305 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001306 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001307 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001308 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001309
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001310 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001311 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1312 file, linenum, newpeer->addr.ss_family, args[2]);
1313 err_code |= ERR_ALERT | ERR_FATAL;
1314 goto out;
1315 }
1316
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001317 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001318
1319 if (strcmp(newpeer->id, localpeer) == 0) {
1320 /* Current is local peer, it define a frontend */
1321 newpeer->local = 1;
1322
1323 if (!curpeers->peers_fe) {
1324 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1325 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1326 err_code |= ERR_ALERT | ERR_ABORT;
1327 goto out;
1328 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001329
Willy Tarreau237250c2011-07-29 01:49:03 +02001330 init_new_proxy(curpeers->peers_fe);
1331 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001332
1333 curpeers->peers_fe->last_change = now.tv_sec;
1334 curpeers->peers_fe->id = strdup(args[1]);
1335 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001336 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001337 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1338 curpeers->peers_fe->timeout.connect = 5000;
1339 curpeers->peers_fe->accept = peer_accept;
1340 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001341
1342 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1343
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001344 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1345 if (err_msg && *err_msg) {
1346 indent_msg(&err_msg, 2);
1347 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1348 }
1349 else
1350 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1351 file, linenum, args[0], args[1], args[2]);
1352 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001353 err_code |= ERR_FATAL;
1354 goto out;
1355 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001356
1357 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1358 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1359 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1360 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1361 l->accept = session_accept;
1362 l->handler = process_session;
1363 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1364 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1365 global.maxsock += l->maxconn;
1366 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001367 }
1368 }
1369 } /* neither "peer" nor "peers" */
1370 else if (*args[0] != 0) {
1371 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1372 err_code |= ERR_ALERT | ERR_FATAL;
1373 goto out;
1374 }
1375
1376out:
1377 return err_code;
1378}
1379
1380
Willy Tarreau3842f002009-06-14 11:39:52 +02001381int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382{
1383 static struct proxy *curproxy = NULL;
1384 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001385 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001386 int rc;
1387 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001388 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001389 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001390 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001391 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001392 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393
Willy Tarreau977b8e42006-12-29 14:19:17 +01001394 if (!strcmp(args[0], "listen"))
1395 rc = PR_CAP_LISTEN;
1396 else if (!strcmp(args[0], "frontend"))
1397 rc = PR_CAP_FE | PR_CAP_RS;
1398 else if (!strcmp(args[0], "backend"))
1399 rc = PR_CAP_BE | PR_CAP_RS;
1400 else if (!strcmp(args[0], "ruleset"))
1401 rc = PR_CAP_RS;
1402 else
1403 rc = PR_CAP_NONE;
1404
1405 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406 if (!*args[1]) {
1407 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1408 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1409 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001410 err_code |= ERR_ALERT | ERR_ABORT;
1411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001413
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001414 err = invalid_char(args[1]);
1415 if (err) {
1416 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1417 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001418 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001419 }
1420
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001421 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1422 /*
1423 * If there are two proxies with the same name only following
1424 * combinations are allowed:
1425 *
1426 * listen backend frontend ruleset
1427 * listen - - - -
1428 * backend - - OK -
1429 * frontend - OK - -
1430 * ruleset - - - -
1431 */
1432
1433 if (!strcmp(curproxy->id, args[1]) &&
1434 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1435 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001436 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1437 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1438 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001439 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001440 }
1441 }
1442
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1444 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001445 err_code |= ERR_ALERT | ERR_ABORT;
1446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001447 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001448
Willy Tarreau97cb7802010-01-03 20:23:58 +01001449 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 curproxy->next = proxy;
1451 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001452 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001453 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001454 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001456 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457
1458 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001459 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001460 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001461 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001462
Willy Tarreau4348fad2012-09-20 16:48:07 +02001463 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1464
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001465 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1466 if (err_msg && *err_msg) {
1467 indent_msg(&err_msg, 2);
1468 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1469 }
1470 else
1471 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1472 file, linenum, args[0], args[1], args[2]);
1473 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001474 err_code |= ERR_FATAL;
1475 goto out;
1476 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001477
Willy Tarreau4348fad2012-09-20 16:48:07 +02001478 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001479 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 }
1482
1483 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001484 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001485 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001486
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001489 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001490 curproxy->no_options = defproxy.no_options;
1491 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001492 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001493 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001494 curproxy->except_net = defproxy.except_net;
1495 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001496 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001497 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001499 if (defproxy.fwdfor_hdr_len) {
1500 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1501 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1502 }
1503
Willy Tarreaub86db342009-11-30 11:50:16 +01001504 if (defproxy.orgto_hdr_len) {
1505 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1506 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1507 }
1508
Mark Lamourinec2247f02012-01-04 13:02:01 -05001509 if (defproxy.server_id_hdr_len) {
1510 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1511 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1512 }
1513
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 if (curproxy->cap & PR_CAP_FE) {
1515 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001516 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001517 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001518
1519 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001520 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1521 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001522
1523 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001525
Willy Tarreau977b8e42006-12-29 14:19:17 +01001526 if (curproxy->cap & PR_CAP_BE) {
1527 curproxy->fullconn = defproxy.fullconn;
1528 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001530 if (defproxy.check_req) {
1531 curproxy->check_req = calloc(1, defproxy.check_len);
1532 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1533 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001534 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001536 if (defproxy.expect_str) {
1537 curproxy->expect_str = strdup(defproxy.expect_str);
1538 if (defproxy.expect_regex) {
1539 /* note: this regex is known to be valid */
1540 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1541 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1542 }
1543 }
1544
Willy Tarreau67402132012-05-31 20:40:20 +02001545 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001546 if (defproxy.cookie_name)
1547 curproxy->cookie_name = strdup(defproxy.cookie_name);
1548 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001549 if (defproxy.cookie_domain)
1550 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001551
Willy Tarreau31936852010-10-06 16:59:56 +02001552 if (defproxy.cookie_maxidle)
1553 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1554
1555 if (defproxy.cookie_maxlife)
1556 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1557
Emeric Brun647caf12009-06-30 17:57:00 +02001558 if (defproxy.rdp_cookie_name)
1559 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1560 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1561
Willy Tarreau01732802007-11-01 22:48:15 +01001562 if (defproxy.url_param_name)
1563 curproxy->url_param_name = strdup(defproxy.url_param_name);
1564 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001565
Benoitaffb4812009-03-25 13:02:10 +01001566 if (defproxy.hh_name)
1567 curproxy->hh_name = strdup(defproxy.hh_name);
1568 curproxy->hh_len = defproxy.hh_len;
1569 curproxy->hh_match_domain = defproxy.hh_match_domain;
1570
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001571 if (defproxy.iface_name)
1572 curproxy->iface_name = strdup(defproxy.iface_name);
1573 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001574 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001576 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001577 if (defproxy.capture_name)
1578 curproxy->capture_name = strdup(defproxy.capture_name);
1579 curproxy->capture_namelen = defproxy.capture_namelen;
1580 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582
Willy Tarreau977b8e42006-12-29 14:19:17 +01001583 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001584 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001585 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001586 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001587 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001588 curproxy->uri_auth = defproxy.uri_auth;
1589 curproxy->mon_net = defproxy.mon_net;
1590 curproxy->mon_mask = defproxy.mon_mask;
1591 if (defproxy.monitor_uri)
1592 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1593 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001594 if (defproxy.defbe.name)
1595 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001596
1597 /* get either a pointer to the logformat string or a copy of it */
1598 curproxy->logformat_string = defproxy.logformat_string;
1599 if (curproxy->logformat_string &&
1600 curproxy->logformat_string != default_http_log_format &&
1601 curproxy->logformat_string != default_tcp_log_format &&
1602 curproxy->logformat_string != clf_http_log_format)
1603 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001604 }
1605
1606 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001607 curproxy->timeout.connect = defproxy.timeout.connect;
1608 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001609 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001610 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001611 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001612 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001613 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001614 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001615 curproxy->source_addr = defproxy.source_addr;
1616 }
1617
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001619
1620 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001621 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001622 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001623 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001624 LIST_INIT(&node->list);
1625 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1626 }
1627
Willy Tarreau196729e2012-05-31 19:30:26 +02001628 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1629 if (curproxy->uniqueid_format_string)
1630 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001631
1632 /* copy default header unique id */
1633 if (defproxy.header_unique_id)
1634 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1635
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001637 curproxy->conf.used_listener_id = EB_ROOT;
1638 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001639
Willy Tarreau93893792009-07-23 13:19:11 +02001640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 }
1642 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1643 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001644 /* FIXME-20070101: we should do this too at the end of the
1645 * config parsing to free all default values.
1646 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001647 free(defproxy.check_req);
1648 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001649 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001650 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001651 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001652 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001653 free(defproxy.capture_name);
1654 free(defproxy.monitor_uri);
1655 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001656 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001657 free(defproxy.fwdfor_hdr_name);
1658 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001659 free(defproxy.orgto_hdr_name);
1660 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001661 free(defproxy.server_id_hdr_name);
1662 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001663 free(defproxy.expect_str);
1664 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001665
Willy Tarreau39b06652012-06-01 10:58:06 +02001666 if (defproxy.logformat_string != default_http_log_format &&
1667 defproxy.logformat_string != default_tcp_log_format &&
1668 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001669 free(defproxy.logformat_string);
1670
1671 free(defproxy.uniqueid_format_string);
1672
Willy Tarreaua534fea2008-08-03 12:19:50 +02001673 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001674 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001675
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 /* we cannot free uri_auth because it might already be used */
1677 init_default_instance();
1678 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001679 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001681 }
1682 else if (curproxy == NULL) {
1683 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 }
1687
Willy Tarreau977b8e42006-12-29 14:19:17 +01001688
1689 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001691 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001692 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001693 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001694
Willy Tarreaubaaee002006-06-26 02:48:02 +02001695 if (curproxy == &defproxy) {
1696 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001700 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001701 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001702
Emeric Bruned760922010-10-22 17:59:25 +02001703 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001704 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001706 err_code |= ERR_ALERT | ERR_FATAL;
1707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001709
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001710 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001711 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001712
1713 /* NOTE: the following line might create several listeners if there
1714 * are comma-separated IPs or port ranges. So all further processing
1715 * will have to be applied to all listeners created after last_listen.
1716 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001717 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1718 if (err_msg && *err_msg) {
1719 indent_msg(&err_msg, 2);
1720 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1721 }
1722 else
1723 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1724 file, linenum, args[0], args[1]);
1725 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
1728 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001729
Willy Tarreau4348fad2012-09-20 16:48:07 +02001730 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1731 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001732 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001733 }
1734
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001735 cur_arg = 2;
1736 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001737 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001738 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001739 char *err;
1740
Willy Tarreau26982662012-09-12 23:17:10 +02001741 kw = bind_find_kw(args[cur_arg]);
1742 if (kw) {
1743 char *err = NULL;
1744 int code;
1745
1746 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001747 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1748 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001749 cur_arg += 1 + kw->skip ;
1750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
1752 }
1753
Willy Tarreau4348fad2012-09-20 16:48:07 +02001754 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001755 err_code |= code;
1756
1757 if (code) {
1758 if (err && *err) {
1759 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001760 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001761 }
1762 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001763 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1764 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001765 if (code & ERR_FATAL) {
1766 free(err);
1767 cur_arg += 1 + kw->skip;
1768 goto out;
1769 }
1770 }
1771 free(err);
1772 cur_arg += 1 + kw->skip;
1773 continue;
1774 }
1775
Willy Tarreau8638f482012-09-18 18:01:17 +02001776 err = NULL;
1777 if (!bind_dumped) {
1778 bind_dump_kws(&err);
1779 indent_msg(&err, 4);
1780 bind_dumped = 1;
1781 }
1782
1783 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1784 file, linenum, args[0], args[1], args[cur_arg],
1785 err ? " Registered keywords :" : "", err ? err : "");
1786 free(err);
1787
Willy Tarreau93893792009-07-23 13:19:11 +02001788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001790 }
Willy Tarreau93893792009-07-23 13:19:11 +02001791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 }
1793 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1794 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1795 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1796 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001799 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001800 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001801 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803 /* flush useless bits */
1804 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001807 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001808 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001809 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810
Willy Tarreau1c47f852006-07-09 08:22:27 +02001811 if (!*args[1]) {
1812 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1813 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001816 }
1817
Willy Tarreaua534fea2008-08-03 12:19:50 +02001818 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001819 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001820 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001821 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001822 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1823
Willy Tarreau93893792009-07-23 13:19:11 +02001824 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001825 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001826 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1827 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1828 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1829 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1830 else {
1831 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001834 }
1835 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001836 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001837 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001838
1839 if (curproxy == &defproxy) {
1840 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1841 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001842 err_code |= ERR_ALERT | ERR_FATAL;
1843 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001844 }
1845
1846 if (!*args[1]) {
1847 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1848 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001849 err_code |= ERR_ALERT | ERR_FATAL;
1850 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001851 }
1852
1853 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001854 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001855
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001856 if (curproxy->uuid <= 0) {
1857 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001858 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001861 }
1862
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001863 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1864 if (node) {
1865 struct proxy *target = container_of(node, struct proxy, conf.id);
1866 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1867 file, linenum, proxy_type_str(curproxy), curproxy->id,
1868 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871 }
1872 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001873 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001874 else if (!strcmp(args[0], "description")) {
1875 int i, len=0;
1876 char *d;
1877
Cyril Bonté99ed3272010-01-24 23:29:44 +01001878 if (curproxy == &defproxy) {
1879 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1880 file, linenum, args[0]);
1881 err_code |= ERR_ALERT | ERR_FATAL;
1882 goto out;
1883 }
1884
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001885 if (!*args[1]) {
1886 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1887 file, linenum, args[0]);
1888 return -1;
1889 }
1890
1891 for(i=1; *args[i]; i++)
1892 len += strlen(args[i])+1;
1893
1894 d = (char *)calloc(1, len);
1895 curproxy->desc = d;
1896
1897 d += sprintf(d, "%s", args[1]);
1898 for(i=2; *args[i]; i++)
1899 d += sprintf(d, " %s", args[i]);
1900
1901 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1903 curproxy->state = PR_STSTOPPED;
1904 }
1905 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1906 curproxy->state = PR_STNEW;
1907 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001908 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1909 int cur_arg = 1;
1910 unsigned int set = 0;
1911
1912 while (*args[cur_arg]) {
1913 int u;
1914 if (strcmp(args[cur_arg], "all") == 0) {
1915 set = 0;
1916 break;
1917 }
1918 else if (strcmp(args[cur_arg], "odd") == 0) {
1919 set |= 0x55555555;
1920 }
1921 else if (strcmp(args[cur_arg], "even") == 0) {
1922 set |= 0xAAAAAAAA;
1923 }
1924 else {
1925 u = str2uic(args[cur_arg]);
1926 if (u < 1 || u > 32) {
1927 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1928 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001931 }
1932 if (u > global.nbproc) {
1933 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1934 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001936 }
1937 set |= 1 << (u - 1);
1938 }
1939 cur_arg++;
1940 }
1941 curproxy->bind_proc = set;
1942 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001943 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001944 if (curproxy == &defproxy) {
1945 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
1947 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001948 }
1949
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001950 err = invalid_char(args[1]);
1951 if (err) {
1952 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1953 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001955 }
1956
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001957 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
1958 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
1959 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_ALERT | ERR_FATAL;
1961 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001962 }
1963 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001964 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1965 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966
Willy Tarreau977b8e42006-12-29 14:19:17 +01001967 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001968 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001969
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970 if (*(args[1]) == 0) {
1971 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1972 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001973 err_code |= ERR_ALERT | ERR_FATAL;
1974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001976
Willy Tarreau67402132012-05-31 20:40:20 +02001977 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001978 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001979 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001980 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 curproxy->cookie_name = strdup(args[1]);
1982 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001983
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 cur_arg = 2;
1985 while (*(args[cur_arg])) {
1986 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001987 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 }
1989 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001990 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991 }
1992 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001993 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 }
1995 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001996 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 }
1998 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001999 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002001 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002002 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002005 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002006 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002007 else if (!strcmp(args[cur_arg], "httponly")) {
2008 curproxy->ck_opts |= PR_CK_HTTPONLY;
2009 }
2010 else if (!strcmp(args[cur_arg], "secure")) {
2011 curproxy->ck_opts |= PR_CK_SECURE;
2012 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002013 else if (!strcmp(args[cur_arg], "domain")) {
2014 if (!*args[cur_arg + 1]) {
2015 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2016 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002019 }
2020
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002021 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002022 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002023 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2024 " dots nor does not start with a dot."
2025 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002026 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002027 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002028 }
2029
2030 err = invalid_domainchar(args[cur_arg + 1]);
2031 if (err) {
2032 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2033 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002036 }
2037
Willy Tarreau68a897b2009-12-03 23:28:34 +01002038 if (!curproxy->cookie_domain) {
2039 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2040 } else {
2041 /* one domain was already specified, add another one by
2042 * building the string which will be returned along with
2043 * the cookie.
2044 */
2045 char *new_ptr;
2046 int new_len = strlen(curproxy->cookie_domain) +
2047 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2048 new_ptr = malloc(new_len);
2049 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2050 free(curproxy->cookie_domain);
2051 curproxy->cookie_domain = new_ptr;
2052 }
Willy Tarreau31936852010-10-06 16:59:56 +02002053 cur_arg++;
2054 }
2055 else if (!strcmp(args[cur_arg], "maxidle")) {
2056 unsigned int maxidle;
2057 const char *res;
2058
2059 if (!*args[cur_arg + 1]) {
2060 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2061 file, linenum, args[cur_arg]);
2062 err_code |= ERR_ALERT | ERR_FATAL;
2063 goto out;
2064 }
2065
2066 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2067 if (res) {
2068 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2069 file, linenum, *res, args[cur_arg]);
2070 err_code |= ERR_ALERT | ERR_FATAL;
2071 goto out;
2072 }
2073 curproxy->cookie_maxidle = maxidle;
2074 cur_arg++;
2075 }
2076 else if (!strcmp(args[cur_arg], "maxlife")) {
2077 unsigned int maxlife;
2078 const char *res;
2079
2080 if (!*args[cur_arg + 1]) {
2081 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2082 file, linenum, args[cur_arg]);
2083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
2085 }
2086
2087 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2088 if (res) {
2089 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2090 file, linenum, *res, args[cur_arg]);
2091 err_code |= ERR_ALERT | ERR_FATAL;
2092 goto out;
2093 }
2094 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002095 cur_arg++;
2096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002098 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 +02002099 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 }
2103 cur_arg++;
2104 }
Willy Tarreau67402132012-05-31 20:40:20 +02002105 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2107 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002108 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 }
2110
Willy Tarreau67402132012-05-31 20:40:20 +02002111 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2113 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002116
Willy Tarreau67402132012-05-31 20:40:20 +02002117 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002118 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2119 file, linenum);
2120 err_code |= ERR_ALERT | ERR_FATAL;
2121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002123 else if (!strcmp(args[0], "persist")) { /* persist */
2124 if (*(args[1]) == 0) {
2125 Alert("parsing [%s:%d] : missing persist method.\n",
2126 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002127 err_code |= ERR_ALERT | ERR_FATAL;
2128 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002129 }
2130
2131 if (!strncmp(args[1], "rdp-cookie", 10)) {
2132 curproxy->options2 |= PR_O2_RDPC_PRST;
2133
Emeric Brunb982a3d2010-01-04 15:45:53 +01002134 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002135 const char *beg, *end;
2136
2137 beg = args[1] + 11;
2138 end = strchr(beg, ')');
2139
2140 if (!end || end == beg) {
2141 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2142 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002145 }
2146
2147 free(curproxy->rdp_cookie_name);
2148 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2149 curproxy->rdp_cookie_len = end-beg;
2150 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002151 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002152 free(curproxy->rdp_cookie_name);
2153 curproxy->rdp_cookie_name = strdup("msts");
2154 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2155 }
2156 else { /* syntax */
2157 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2158 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002161 }
2162 }
2163 else {
2164 Alert("parsing [%s:%d] : unknown persist method.\n",
2165 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002168 }
2169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002171 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002173 if (curproxy == &defproxy) {
2174 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178
Willy Tarreau977b8e42006-12-29 14:19:17 +01002179 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002180 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002181
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002183 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 }
2188 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002189 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 curproxy->appsession_name = strdup(args[1]);
2191 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2192 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002193 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2194 if (err) {
2195 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2196 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002199 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002200 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002201
Willy Tarreau51041c72007-09-09 21:56:53 +02002202 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2203 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_ABORT;
2205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002207
2208 cur_arg = 6;
2209 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002210 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2211 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002212 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002213 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002214 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002215 } else if (!strcmp(args[cur_arg], "prefix")) {
2216 curproxy->options2 |= PR_O2_AS_PFX;
2217 } else if (!strcmp(args[cur_arg], "mode")) {
2218 if (!*args[cur_arg + 1]) {
2219 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2220 file, linenum, args[0], args[cur_arg]);
2221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
2223 }
2224
2225 cur_arg++;
2226 if (!strcmp(args[cur_arg], "query-string")) {
2227 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2228 curproxy->options2 |= PR_O2_AS_M_QS;
2229 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2230 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2231 curproxy->options2 |= PR_O2_AS_M_PP;
2232 } else {
2233 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
2236 }
2237 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002238 cur_arg++;
2239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 } /* Url App Session */
2241 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002242 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002244
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002246 if (curproxy == &defproxy) {
2247 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
2250 }
2251
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 if (*(args[4]) == 0) {
2253 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2254 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002255 err_code |= ERR_ALERT | ERR_FATAL;
2256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002258 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 curproxy->capture_name = strdup(args[2]);
2260 curproxy->capture_namelen = strlen(curproxy->capture_name);
2261 curproxy->capture_len = atol(args[4]);
2262 if (curproxy->capture_len >= CAPTURE_LEN) {
2263 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2264 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002265 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 curproxy->capture_len = CAPTURE_LEN - 1;
2267 }
2268 curproxy->to_log |= LW_COOKIE;
2269 }
2270 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2271 struct cap_hdr *hdr;
2272
2273 if (curproxy == &defproxy) {
2274 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 +02002275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 }
2278
2279 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2280 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2281 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284 }
2285
2286 hdr = calloc(sizeof(struct cap_hdr), 1);
2287 hdr->next = curproxy->req_cap;
2288 hdr->name = strdup(args[3]);
2289 hdr->namelen = strlen(args[3]);
2290 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002291 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 hdr->index = curproxy->nb_req_cap++;
2293 curproxy->req_cap = hdr;
2294 curproxy->to_log |= LW_REQHDR;
2295 }
2296 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2297 struct cap_hdr *hdr;
2298
2299 if (curproxy == &defproxy) {
2300 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 +02002301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 }
2304
2305 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2306 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2307 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310 }
2311 hdr = calloc(sizeof(struct cap_hdr), 1);
2312 hdr->next = curproxy->rsp_cap;
2313 hdr->name = strdup(args[3]);
2314 hdr->namelen = strlen(args[3]);
2315 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002316 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 hdr->index = curproxy->nb_rsp_cap++;
2318 curproxy->rsp_cap = hdr;
2319 curproxy->to_log |= LW_RSPHDR;
2320 }
2321 else {
2322 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2323 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 }
2327 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002330 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002331
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 if (*(args[1]) == 0) {
2333 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2334 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 }
2338 curproxy->conn_retries = atol(args[1]);
2339 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002340 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002341 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002342
2343 if (curproxy == &defproxy) {
2344 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
2347 }
2348
Willy Tarreauff011f22011-01-06 17:51:27 +01002349 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 +01002350 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2351 file, linenum, args[0]);
2352 err_code |= ERR_WARN;
2353 }
2354
Willy Tarreauff011f22011-01-06 17:51:27 +01002355 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002356
Willy Tarreauff011f22011-01-06 17:51:27 +01002357 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002358 err_code |= ERR_ALERT | ERR_ABORT;
2359 goto out;
2360 }
2361
Willy Tarreauff011f22011-01-06 17:51:27 +01002362 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2363 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002364 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002365 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2366 /* set the header name and length into the proxy structure */
2367 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2368 err_code |= ERR_WARN;
2369
2370 if (!*args[1]) {
2371 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2372 file, linenum, args[0]);
2373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
2375 }
2376
2377 /* set the desired header name */
2378 free(curproxy->server_id_hdr_name);
2379 curproxy->server_id_hdr_name = strdup(args[1]);
2380 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2381 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002382 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002383 if (curproxy == &defproxy) {
2384 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002387 }
2388
Willy Tarreauef6494c2010-01-28 17:12:36 +01002389 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002390 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2391 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002394 }
2395
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002396 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2397 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2398 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002401 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002402
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002403 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002404 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002405 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002406 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002407 struct redirect_rule *rule;
2408 int cur_arg;
2409 int type = REDIRECT_TYPE_NONE;
2410 int code = 302;
2411 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002412 char *cookie = NULL;
2413 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002414 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002415
Cyril Bonté99ed3272010-01-24 23:29:44 +01002416 if (curproxy == &defproxy) {
2417 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002422 cur_arg = 1;
2423 while (*(args[cur_arg])) {
2424 if (!strcmp(args[cur_arg], "location")) {
2425 if (!*args[cur_arg + 1]) {
2426 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2427 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002430 }
2431
2432 type = REDIRECT_TYPE_LOCATION;
2433 cur_arg++;
2434 destination = args[cur_arg];
2435 }
2436 else if (!strcmp(args[cur_arg], "prefix")) {
2437 if (!*args[cur_arg + 1]) {
2438 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2439 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002442 }
2443
2444 type = REDIRECT_TYPE_PREFIX;
2445 cur_arg++;
2446 destination = args[cur_arg];
2447 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002448 else if (!strcmp(args[cur_arg], "scheme")) {
2449 if (!*args[cur_arg + 1]) {
2450 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2451 file, linenum, args[0], args[cur_arg]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455
2456 type = REDIRECT_TYPE_SCHEME;
2457 cur_arg++;
2458 destination = args[cur_arg];
2459 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002460 else if (!strcmp(args[cur_arg], "set-cookie")) {
2461 if (!*args[cur_arg + 1]) {
2462 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2463 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002466 }
2467
2468 cur_arg++;
2469 cookie = args[cur_arg];
2470 cookie_set = 1;
2471 }
2472 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2473 if (!*args[cur_arg + 1]) {
2474 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2475 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002478 }
2479
2480 cur_arg++;
2481 cookie = args[cur_arg];
2482 cookie_set = 0;
2483 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002484 else if (!strcmp(args[cur_arg],"code")) {
2485 if (!*args[cur_arg + 1]) {
2486 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2487 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002490 }
2491 cur_arg++;
2492 code = atol(args[cur_arg]);
2493 if (code < 301 || code > 303) {
2494 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2495 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002498 }
2499 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002500 else if (!strcmp(args[cur_arg],"drop-query")) {
2501 flags |= REDIRECT_FLAG_DROP_QS;
2502 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002503 else if (!strcmp(args[cur_arg],"append-slash")) {
2504 flags |= REDIRECT_FLAG_APPEND_SLASH;
2505 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002506 else if (strcmp(args[cur_arg], "if") == 0 ||
2507 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002508 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002509 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002510 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2511 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
2514 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002515 break;
2516 }
2517 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002518 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 +02002519 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002522 }
2523 cur_arg++;
2524 }
2525
2526 if (type == REDIRECT_TYPE_NONE) {
2527 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2528 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002531 }
2532
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002533 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2534 rule->cond = cond;
2535 rule->rdr_str = strdup(destination);
2536 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002537 if (cookie) {
2538 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002539 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002540 */
2541 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002542 if (cookie_set) {
2543 rule->cookie_str = malloc(rule->cookie_len + 10);
2544 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2545 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2546 rule->cookie_len += 9;
2547 } else {
2548 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002549 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002550 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2551 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002552 }
2553 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002554 rule->type = type;
2555 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002556 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002557 LIST_INIT(&rule->list);
2558 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002559 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2560 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002561 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002562 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002563 struct switching_rule *rule;
2564
Willy Tarreaub099aca2008-10-12 17:26:37 +02002565 if (curproxy == &defproxy) {
2566 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002569 }
2570
Willy Tarreau55ea7572007-06-17 19:56:27 +02002571 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002573
2574 if (*(args[1]) == 0) {
2575 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002578 }
2579
Willy Tarreauef6494c2010-01-28 17:12:36 +01002580 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002581 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002585 }
2586
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002587 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2588 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2589 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002592 }
2593
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002594 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002595
Willy Tarreau55ea7572007-06-17 19:56:27 +02002596 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2597 rule->cond = cond;
2598 rule->be.name = strdup(args[1]);
2599 LIST_INIT(&rule->list);
2600 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2601 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002602 else if (strcmp(args[0], "use-server") == 0) {
2603 struct server_rule *rule;
2604
2605 if (curproxy == &defproxy) {
2606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
2609 }
2610
2611 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2612 err_code |= ERR_WARN;
2613
2614 if (*(args[1]) == 0) {
2615 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2616 err_code |= ERR_ALERT | ERR_FATAL;
2617 goto out;
2618 }
2619
2620 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2621 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2622 file, linenum, args[0]);
2623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
2625 }
2626
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002627 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2628 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2629 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
2633
2634 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2635
2636 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2637 rule->cond = cond;
2638 rule->srv.name = strdup(args[1]);
2639 LIST_INIT(&rule->list);
2640 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2641 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2642 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002643 else if ((!strcmp(args[0], "force-persist")) ||
2644 (!strcmp(args[0], "ignore-persist"))) {
2645 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002646
2647 if (curproxy == &defproxy) {
2648 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
2651 }
2652
2653 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2654 err_code |= ERR_WARN;
2655
Willy Tarreauef6494c2010-01-28 17:12:36 +01002656 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002657 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2658 file, linenum, args[0]);
2659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
2661 }
2662
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002663 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2664 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2665 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
2668 }
2669
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002670 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002671
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002672 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002673 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002674 if (!strcmp(args[0], "force-persist")) {
2675 rule->type = PERSIST_TYPE_FORCE;
2676 } else {
2677 rule->type = PERSIST_TYPE_IGNORE;
2678 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002679 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002680 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002681 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002682 else if (!strcmp(args[0], "stick-table")) {
2683 int myidx = 1;
2684
Emeric Brun32da3c42010-09-23 18:39:19 +02002685 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002686 curproxy->table.type = (unsigned int)-1;
2687 while (*args[myidx]) {
2688 const char *err;
2689
2690 if (strcmp(args[myidx], "size") == 0) {
2691 myidx++;
2692 if (!*(args[myidx])) {
2693 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2694 file, linenum, args[myidx-1]);
2695 err_code |= ERR_ALERT | ERR_FATAL;
2696 goto out;
2697 }
2698 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2699 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2700 file, linenum, *err, args[myidx-1]);
2701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
2703 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002704 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002705 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002706 else if (strcmp(args[myidx], "peers") == 0) {
2707 myidx++;
2708 if (!*(args[myidx])) {
2709 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2710 file, linenum, args[myidx-1]);
2711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
2713 }
2714 curproxy->table.peers.name = strdup(args[myidx++]);
2715 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002716 else if (strcmp(args[myidx], "expire") == 0) {
2717 myidx++;
2718 if (!*(args[myidx])) {
2719 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2720 file, linenum, args[myidx-1]);
2721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
2723 }
2724 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2725 if (err) {
2726 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2727 file, linenum, *err, args[myidx-1]);
2728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
2730 }
2731 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002732 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002733 }
2734 else if (strcmp(args[myidx], "nopurge") == 0) {
2735 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002736 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002737 }
2738 else if (strcmp(args[myidx], "type") == 0) {
2739 myidx++;
2740 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2741 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2742 file, linenum, args[myidx]);
2743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
2745 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002746 /* myidx already points to next arg */
2747 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002748 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002749 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002750 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002751
2752 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002753 nw = args[myidx];
2754 while (*nw) {
2755 /* the "store" keyword supports a comma-separated list */
2756 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002757 sa = NULL; /* store arg */
2758 while (*nw && *nw != ',') {
2759 if (*nw == '(') {
2760 *nw = 0;
2761 sa = ++nw;
2762 while (*nw != ')') {
2763 if (!*nw) {
2764 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2765 file, linenum, args[0], cw);
2766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769 nw++;
2770 }
2771 *nw = '\0';
2772 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002773 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002774 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002775 if (*nw)
2776 *nw++ = '\0';
2777 type = stktable_get_data_type(cw);
2778 if (type < 0) {
2779 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2780 file, linenum, args[0], cw);
2781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
2783 }
Willy Tarreauac782882010-06-20 10:41:54 +02002784
2785 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2786 switch (err) {
2787 case PE_NONE: break;
2788 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002789 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2790 file, linenum, args[0], cw);
2791 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002792 break;
2793
2794 case PE_ARG_MISSING:
2795 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2796 file, linenum, args[0], cw);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
2799
2800 case PE_ARG_NOT_USED:
2801 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2802 file, linenum, args[0], cw);
2803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
2805
2806 default:
2807 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2808 file, linenum, args[0], cw);
2809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002811 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002812 }
2813 myidx++;
2814 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002815 else {
2816 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2817 file, linenum, args[myidx]);
2818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002820 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002821 }
2822
2823 if (!curproxy->table.size) {
2824 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2825 file, linenum);
2826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
2828 }
2829
2830 if (curproxy->table.type == (unsigned int)-1) {
2831 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2832 file, linenum);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
2836 }
2837 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002838 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002839 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002840 int myidx = 0;
2841 const char *name = NULL;
2842 int flags;
2843
2844 if (curproxy == &defproxy) {
2845 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848 }
2849
2850 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2851 err_code |= ERR_WARN;
2852 goto out;
2853 }
2854
2855 myidx++;
2856 if ((strcmp(args[myidx], "store") == 0) ||
2857 (strcmp(args[myidx], "store-request") == 0)) {
2858 myidx++;
2859 flags = STK_IS_STORE;
2860 }
2861 else if (strcmp(args[myidx], "store-response") == 0) {
2862 myidx++;
2863 flags = STK_IS_STORE | STK_ON_RSP;
2864 }
2865 else if (strcmp(args[myidx], "match") == 0) {
2866 myidx++;
2867 flags = STK_IS_MATCH;
2868 }
2869 else if (strcmp(args[myidx], "on") == 0) {
2870 myidx++;
2871 flags = STK_IS_MATCH | STK_IS_STORE;
2872 }
2873 else {
2874 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
2877 }
2878
2879 if (*(args[myidx]) == 0) {
2880 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2881 err_code |= ERR_ALERT | ERR_FATAL;
2882 goto out;
2883 }
2884
David du Colombier7af46052012-05-16 14:16:48 +02002885 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002886 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002887 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
2891
2892 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002893 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002894 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2895 file, linenum, args[0], expr->fetch->kw);
2896 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002897 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002898 goto out;
2899 }
2900 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002901 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002902 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2903 file, linenum, args[0], expr->fetch->kw);
2904 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002905 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002906 goto out;
2907 }
2908 }
2909
2910 if (strcmp(args[myidx], "table") == 0) {
2911 myidx++;
2912 name = args[myidx++];
2913 }
2914
Willy Tarreauef6494c2010-01-28 17:12:36 +01002915 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002916 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
2917 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
2918 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002919 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002920 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002921 goto out;
2922 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002923 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002924 else if (*(args[myidx])) {
2925 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2926 file, linenum, args[0], args[myidx]);
2927 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002928 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002929 goto out;
2930 }
Emeric Brun97679e72010-09-23 17:56:44 +02002931 if (flags & STK_ON_RSP)
2932 err_code |= warnif_cond_requires_req(cond, file, linenum);
2933 else
2934 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002935
Emeric Brunb982a3d2010-01-04 15:45:53 +01002936 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2937 rule->cond = cond;
2938 rule->expr = expr;
2939 rule->flags = flags;
2940 rule->table.name = name ? strdup(name) : NULL;
2941 LIST_INIT(&rule->list);
2942 if (flags & STK_ON_RSP)
2943 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2944 else
2945 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002948 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002949 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002950
Willy Tarreaubaaee002006-06-26 02:48:02 +02002951 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2952 curproxy->uri_auth = NULL; /* we must detach from the default config */
2953
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002954 if (!*args[1]) {
2955 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002956 } else if (!strcmp(args[1], "admin")) {
2957 struct stats_admin_rule *rule;
2958
2959 if (curproxy == &defproxy) {
2960 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
2964
2965 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2966 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2967 err_code |= ERR_ALERT | ERR_ABORT;
2968 goto out;
2969 }
2970
2971 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2972 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2973 file, linenum, args[0], args[1]);
2974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
2976 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002977 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2978 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
2979 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02002980 err_code |= ERR_ALERT | ERR_FATAL;
2981 goto out;
2982 }
2983
2984 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2985
2986 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2987 rule->cond = cond;
2988 LIST_INIT(&rule->list);
2989 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002990 } else if (!strcmp(args[1], "uri")) {
2991 if (*(args[2]) == 0) {
2992 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002995 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2996 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_ALERT | ERR_ABORT;
2998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 }
3000 } else if (!strcmp(args[1], "realm")) {
3001 if (*(args[2]) == 0) {
3002 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3006 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_ABORT;
3008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003010 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003011 unsigned interval;
3012
3013 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3014 if (err) {
3015 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3016 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003019 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3020 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_ALERT | ERR_ABORT;
3022 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003023 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003024 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003025 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003026
3027 if (curproxy == &defproxy) {
3028 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
3031 }
3032
3033 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3034 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3035 err_code |= ERR_ALERT | ERR_ABORT;
3036 goto out;
3037 }
3038
Willy Tarreauff011f22011-01-06 17:51:27 +01003039 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3040 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003041 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3042 file, linenum, args[0]);
3043 err_code |= ERR_WARN;
3044 }
3045
Willy Tarreauff011f22011-01-06 17:51:27 +01003046 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003047
Willy Tarreauff011f22011-01-06 17:51:27 +01003048 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003049 err_code |= ERR_ALERT | ERR_ABORT;
3050 goto out;
3051 }
3052
Willy Tarreauff011f22011-01-06 17:51:27 +01003053 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3054 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003055
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 } else if (!strcmp(args[1], "auth")) {
3057 if (*(args[2]) == 0) {
3058 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
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 Tarreaubaaee002006-06-26 02:48:02 +02003065 }
3066 } else if (!strcmp(args[1], "scope")) {
3067 if (*(args[2]) == 0) {
3068 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3072 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_ABORT;
3074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 }
3076 } else if (!strcmp(args[1], "enable")) {
3077 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3078 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_ABORT;
3080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003082 } else if (!strcmp(args[1], "hide-version")) {
3083 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3084 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_ALERT | ERR_ABORT;
3086 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003087 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003088 } else if (!strcmp(args[1], "show-legends")) {
3089 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3090 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3091 err_code |= ERR_ALERT | ERR_ABORT;
3092 goto out;
3093 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003094 } else if (!strcmp(args[1], "show-node")) {
3095
3096 if (*args[2]) {
3097 int i;
3098 char c;
3099
3100 for (i=0; args[2][i]; i++) {
3101 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003102 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3103 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003104 break;
3105 }
3106
3107 if (!i || args[2][i]) {
3108 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3109 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3110 file, linenum, args[0], args[1]);
3111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
3113 }
3114 }
3115
3116 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3117 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3118 err_code |= ERR_ALERT | ERR_ABORT;
3119 goto out;
3120 }
3121 } else if (!strcmp(args[1], "show-desc")) {
3122 char *desc = NULL;
3123
3124 if (*args[2]) {
3125 int i, len=0;
3126 char *d;
3127
3128 for(i=2; *args[i]; i++)
3129 len += strlen(args[i])+1;
3130
3131 desc = d = (char *)calloc(1, len);
3132
3133 d += sprintf(d, "%s", args[2]);
3134 for(i=3; *args[i]; i++)
3135 d += sprintf(d, " %s", args[i]);
3136 }
3137
3138 if (!*args[2] && !global.desc)
3139 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3140 file, linenum, args[1]);
3141 else {
3142 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3143 free(desc);
3144 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3145 err_code |= ERR_ALERT | ERR_ABORT;
3146 goto out;
3147 }
3148 free(desc);
3149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003151stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003152 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 +01003153 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 }
3157 }
3158 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003159 int optnum;
3160
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003161 if (*(args[1]) == '\0') {
3162 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3163 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003167
3168 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3169 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003170 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3171 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3172 file, linenum, cfg_opts[optnum].name);
3173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
3175 }
Willy Tarreau93893792009-07-23 13:19:11 +02003176 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3177 err_code |= ERR_WARN;
3178 goto out;
3179 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003180
Willy Tarreau3842f002009-06-14 11:39:52 +02003181 curproxy->no_options &= ~cfg_opts[optnum].val;
3182 curproxy->options &= ~cfg_opts[optnum].val;
3183
3184 switch (kwm) {
3185 case KWM_STD:
3186 curproxy->options |= cfg_opts[optnum].val;
3187 break;
3188 case KWM_NO:
3189 curproxy->no_options |= cfg_opts[optnum].val;
3190 break;
3191 case KWM_DEF: /* already cleared */
3192 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003193 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003194
Willy Tarreau93893792009-07-23 13:19:11 +02003195 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003196 }
3197 }
3198
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003199 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3200 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003201 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3202 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3203 file, linenum, cfg_opts2[optnum].name);
3204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
3206 }
Willy Tarreau93893792009-07-23 13:19:11 +02003207 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3208 err_code |= ERR_WARN;
3209 goto out;
3210 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003211
Willy Tarreau3842f002009-06-14 11:39:52 +02003212 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3213 curproxy->options2 &= ~cfg_opts2[optnum].val;
3214
3215 switch (kwm) {
3216 case KWM_STD:
3217 curproxy->options2 |= cfg_opts2[optnum].val;
3218 break;
3219 case KWM_NO:
3220 curproxy->no_options2 |= cfg_opts2[optnum].val;
3221 break;
3222 case KWM_DEF: /* already cleared */
3223 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003224 }
Willy Tarreau93893792009-07-23 13:19:11 +02003225 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003226 }
3227 }
3228
Willy Tarreau3842f002009-06-14 11:39:52 +02003229 if (kwm != KWM_STD) {
3230 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003231 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003234 }
3235
Emeric Brun3a058f32009-06-30 18:26:00 +02003236 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003237 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003239 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003240 if (*(args[2]) != '\0') {
3241 if (!strcmp(args[2], "clf")) {
3242 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003243 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003244 } else {
3245 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003248 }
3249 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003250 if (curproxy->logformat_string != default_http_log_format &&
3251 curproxy->logformat_string != default_tcp_log_format &&
3252 curproxy->logformat_string != clf_http_log_format)
3253 free(curproxy->logformat_string);
3254 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003255 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003256 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003258 if (curproxy->logformat_string != default_http_log_format &&
3259 curproxy->logformat_string != default_tcp_log_format &&
3260 curproxy->logformat_string != clf_http_log_format)
3261 free(curproxy->logformat_string);
3262 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 else if (!strcmp(args[1], "tcpka")) {
3265 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003266 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003268
3269 if (curproxy->cap & PR_CAP_FE)
3270 curproxy->options |= PR_O_TCP_CLI_KA;
3271 if (curproxy->cap & PR_CAP_BE)
3272 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 }
3274 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003275 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_WARN;
3277
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003279 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003280 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003281 curproxy->options2 &= ~PR_O2_CHK_ANY;
3282 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 if (!*args[2]) { /* no argument */
3284 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3285 curproxy->check_len = strlen(DEF_CHECK_REQ);
3286 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003287 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 curproxy->check_req = (char *)malloc(reqlen);
3289 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003290 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003292 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 if (*args[4])
3294 reqlen += strlen(args[4]);
3295 else
3296 reqlen += strlen("HTTP/1.0");
3297
3298 curproxy->check_req = (char *)malloc(reqlen);
3299 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003300 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003302 }
3303 else if (!strcmp(args[1], "ssl-hello-chk")) {
3304 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003305 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307
Willy Tarreaua534fea2008-08-03 12:19:50 +02003308 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003309 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003310 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003311 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 }
Willy Tarreau23677902007-05-08 23:50:35 +02003313 else if (!strcmp(args[1], "smtpchk")) {
3314 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003315 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003316 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003317 curproxy->options2 &= ~PR_O2_CHK_ANY;
3318 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003319
3320 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3321 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3322 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3323 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3324 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3325 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3326 curproxy->check_req = (char *)malloc(reqlen);
3327 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3328 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3329 } else {
3330 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3331 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3332 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3333 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3334 }
3335 }
3336 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003337 else if (!strcmp(args[1], "pgsql-check")) {
3338 /* use PostgreSQL request to check servers' health */
3339 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3340 err_code |= ERR_WARN;
3341
3342 free(curproxy->check_req);
3343 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003344 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003345 curproxy->options2 |= PR_O2_PGSQL_CHK;
3346
3347 if (*(args[2])) {
3348 int cur_arg = 2;
3349
3350 while (*(args[cur_arg])) {
3351 if (strcmp(args[cur_arg], "user") == 0) {
3352 char * packet;
3353 uint32_t packet_len;
3354 uint32_t pv;
3355
3356 /* suboption header - needs additional argument for it */
3357 if (*(args[cur_arg+1]) == 0) {
3358 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3359 file, linenum, args[0], args[1], args[cur_arg]);
3360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
3362 }
3363
3364 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3365 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3366 pv = htonl(0x30000); /* protocol version 3.0 */
3367
3368 packet = (char*) calloc(1, packet_len);
3369
3370 memcpy(packet + 4, &pv, 4);
3371
3372 /* copy "user" */
3373 memcpy(packet + 8, "user", 4);
3374
3375 /* copy username */
3376 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3377
3378 free(curproxy->check_req);
3379 curproxy->check_req = packet;
3380 curproxy->check_len = packet_len;
3381
3382 packet_len = htonl(packet_len);
3383 memcpy(packet, &packet_len, 4);
3384 cur_arg += 2;
3385 } else {
3386 /* unknown suboption - catchall */
3387 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3388 file, linenum, args[0], args[1]);
3389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
3391 }
3392 } /* end while loop */
3393 }
3394 }
3395
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003396 else if (!strcmp(args[1], "redis-check")) {
3397 /* use REDIS PING request to check servers' health */
3398 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3399 err_code |= ERR_WARN;
3400
3401 free(curproxy->check_req);
3402 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003403 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003404 curproxy->options2 |= PR_O2_REDIS_CHK;
3405
3406 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3407 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3408 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3409 }
3410
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003411 else if (!strcmp(args[1], "mysql-check")) {
3412 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003413 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3414 err_code |= ERR_WARN;
3415
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003416 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003417 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003418 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003419 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003420
3421 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3422 * const char mysql40_client_auth_pkt[] = {
3423 * "\x0e\x00\x00" // packet length
3424 * "\x01" // packet number
3425 * "\x00\x00" // client capabilities
3426 * "\x00\x00\x01" // max packet
3427 * "haproxy\x00" // username (null terminated string)
3428 * "\x00" // filler (always 0x00)
3429 * "\x01\x00\x00" // packet length
3430 * "\x00" // packet number
3431 * "\x01" // COM_QUIT command
3432 * };
3433 */
3434
3435 if (*(args[2])) {
3436 int cur_arg = 2;
3437
3438 while (*(args[cur_arg])) {
3439 if (strcmp(args[cur_arg], "user") == 0) {
3440 char *mysqluser;
3441 int packetlen, reqlen, userlen;
3442
3443 /* suboption header - needs additional argument for it */
3444 if (*(args[cur_arg+1]) == 0) {
3445 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3446 file, linenum, args[0], args[1], args[cur_arg]);
3447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
3449 }
3450 mysqluser = args[cur_arg + 1];
3451 userlen = strlen(mysqluser);
3452 packetlen = userlen + 7;
3453 reqlen = packetlen + 9;
3454
3455 free(curproxy->check_req);
3456 curproxy->check_req = (char *)calloc(1, reqlen);
3457 curproxy->check_len = reqlen;
3458
3459 snprintf(curproxy->check_req, 4, "%c%c%c",
3460 ((unsigned char) packetlen & 0xff),
3461 ((unsigned char) (packetlen >> 8) & 0xff),
3462 ((unsigned char) (packetlen >> 16) & 0xff));
3463
3464 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003465 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003466 curproxy->check_req[8] = 1;
3467 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3468 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3469 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3470 cur_arg += 2;
3471 } else {
3472 /* unknown suboption - catchall */
3473 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3474 file, linenum, args[0], args[1]);
3475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
3477 }
3478 } /* end while loop */
3479 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003480 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003481 else if (!strcmp(args[1], "ldap-check")) {
3482 /* use LDAP request to check servers' health */
3483 free(curproxy->check_req);
3484 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003485 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003486 curproxy->options2 |= PR_O2_LDAP_CHK;
3487
3488 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3489 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3490 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3491 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003492 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003493 int cur_arg;
3494
3495 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3496 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003497 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003498
Willy Tarreau87cf5142011-08-19 22:57:24 +02003499 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003500
3501 free(curproxy->fwdfor_hdr_name);
3502 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3503 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3504
3505 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3506 cur_arg = 2;
3507 while (*(args[cur_arg])) {
3508 if (!strcmp(args[cur_arg], "except")) {
3509 /* suboption except - needs additional argument for it */
3510 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3511 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3512 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003515 }
3516 /* flush useless bits */
3517 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003518 cur_arg += 2;
3519 } else if (!strcmp(args[cur_arg], "header")) {
3520 /* suboption header - needs additional argument for it */
3521 if (*(args[cur_arg+1]) == 0) {
3522 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3523 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003526 }
3527 free(curproxy->fwdfor_hdr_name);
3528 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3529 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3530 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003531 } else if (!strcmp(args[cur_arg], "if-none")) {
3532 curproxy->options &= ~PR_O_FF_ALWAYS;
3533 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003534 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003535 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003536 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003537 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003540 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003541 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003542 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003543 else if (!strcmp(args[1], "originalto")) {
3544 int cur_arg;
3545
3546 /* insert x-original-to field, but not for the IP address listed as an except.
3547 * set default options (ie: bitfield, header name, etc)
3548 */
3549
3550 curproxy->options |= PR_O_ORGTO;
3551
3552 free(curproxy->orgto_hdr_name);
3553 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3554 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3555
Willy Tarreau87cf5142011-08-19 22:57:24 +02003556 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003557 cur_arg = 2;
3558 while (*(args[cur_arg])) {
3559 if (!strcmp(args[cur_arg], "except")) {
3560 /* suboption except - needs additional argument for it */
3561 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3562 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3563 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003566 }
3567 /* flush useless bits */
3568 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3569 cur_arg += 2;
3570 } else if (!strcmp(args[cur_arg], "header")) {
3571 /* suboption header - needs additional argument for it */
3572 if (*(args[cur_arg+1]) == 0) {
3573 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3574 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003577 }
3578 free(curproxy->orgto_hdr_name);
3579 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3580 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3581 cur_arg += 2;
3582 } else {
3583 /* unknown suboption - catchall */
3584 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3585 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003588 }
3589 } /* end while loop */
3590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 else {
3592 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003595 }
Willy Tarreau93893792009-07-23 13:19:11 +02003596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003598 else if (!strcmp(args[0], "default_backend")) {
3599 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003601
3602 if (*(args[1]) == 0) {
3603 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003606 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003607 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003608 curproxy->defbe.name = strdup(args[1]);
3609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003611 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003613
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003614 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3615 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 /* enable reconnections to dispatch */
3618 curproxy->options |= PR_O_REDISP;
3619 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003620 else if (!strcmp(args[0], "http-check")) {
3621 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003623
3624 if (strcmp(args[1], "disable-on-404") == 0) {
3625 /* enable a graceful server shutdown on an HTTP 404 response */
3626 curproxy->options |= PR_O_DISABLE404;
3627 }
Willy Tarreauef781042010-01-27 11:53:01 +01003628 else if (strcmp(args[1], "send-state") == 0) {
3629 /* enable emission of the apparent state of a server in HTTP checks */
3630 curproxy->options2 |= PR_O2_CHK_SNDST;
3631 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003632 else if (strcmp(args[1], "expect") == 0) {
3633 const char *ptr_arg;
3634 int cur_arg;
3635
3636 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3637 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3638 err_code |= ERR_ALERT | ERR_FATAL;
3639 goto out;
3640 }
3641
3642 cur_arg = 2;
3643 /* consider exclamation marks, sole or at the beginning of a word */
3644 while (*(ptr_arg = args[cur_arg])) {
3645 while (*ptr_arg == '!') {
3646 curproxy->options2 ^= PR_O2_EXP_INV;
3647 ptr_arg++;
3648 }
3649 if (*ptr_arg)
3650 break;
3651 cur_arg++;
3652 }
3653 /* now ptr_arg points to the beginning of a word past any possible
3654 * exclamation mark, and cur_arg is the argument which holds this word.
3655 */
3656 if (strcmp(ptr_arg, "status") == 0) {
3657 if (!*(args[cur_arg + 1])) {
3658 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3659 file, linenum, args[0], args[1], ptr_arg);
3660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
3662 }
3663 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003664 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003665 curproxy->expect_str = strdup(args[cur_arg + 1]);
3666 }
3667 else if (strcmp(ptr_arg, "string") == 0) {
3668 if (!*(args[cur_arg + 1])) {
3669 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3670 file, linenum, args[0], args[1], ptr_arg);
3671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
3673 }
3674 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003675 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003676 curproxy->expect_str = strdup(args[cur_arg + 1]);
3677 }
3678 else if (strcmp(ptr_arg, "rstatus") == 0) {
3679 if (!*(args[cur_arg + 1])) {
3680 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3681 file, linenum, args[0], args[1], ptr_arg);
3682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
3684 }
3685 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003686 free(curproxy->expect_str);
3687 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3688 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003689 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3690 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3691 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3692 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3693 err_code |= ERR_ALERT | ERR_FATAL;
3694 goto out;
3695 }
3696 }
3697 else if (strcmp(ptr_arg, "rstring") == 0) {
3698 if (!*(args[cur_arg + 1])) {
3699 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3700 file, linenum, args[0], args[1], ptr_arg);
3701 err_code |= ERR_ALERT | ERR_FATAL;
3702 goto out;
3703 }
3704 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003705 free(curproxy->expect_str);
3706 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3707 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003708 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3709 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3710 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3711 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
3714 }
3715 }
3716 else {
3717 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3718 file, linenum, args[0], args[1], ptr_arg);
3719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
3721 }
3722 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003723 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003724 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 +02003725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003727 }
3728 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003729 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003730 if (curproxy == &defproxy) {
3731 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003734 }
3735
Willy Tarreaub80c2302007-11-30 20:51:32 +01003736 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003738
3739 if (strcmp(args[1], "fail") == 0) {
3740 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003741 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003742 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3743 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003746 }
3747
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003748 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3749 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3750 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003753 }
3754 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3755 }
3756 else {
3757 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003760 }
3761 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762#ifdef TPROXY
3763 else if (!strcmp(args[0], "transparent")) {
3764 /* enable transparent proxy connections */
3765 curproxy->options |= PR_O_TRANSP;
3766 }
3767#endif
3768 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003769 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003771
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 if (*(args[1]) == 0) {
3773 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 }
3777 curproxy->maxconn = atol(args[1]);
3778 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003779 else if (!strcmp(args[0], "backlog")) { /* backlog */
3780 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003782
3783 if (*(args[1]) == 0) {
3784 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003787 }
3788 curproxy->backlog = atol(args[1]);
3789 }
Willy Tarreau86034312006-12-29 00:10:33 +01003790 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003791 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003793
Willy Tarreau86034312006-12-29 00:10:33 +01003794 if (*(args[1]) == 0) {
3795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003798 }
3799 curproxy->fullconn = atol(args[1]);
3800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3802 if (*(args[1]) == 0) {
3803 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003807 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3808 if (err) {
3809 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3810 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003813 }
3814 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003815 }
3816 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003817 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 if (curproxy == &defproxy) {
3819 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003823 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003824 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003825
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 if (strchr(args[1], ':') == NULL) {
3827 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003831 sk = str2sa(args[1]);
3832 if (!sk) {
3833 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
3836 }
3837 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003838 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003839 }
3840 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003841 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003843
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003844 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3845 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003850 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3851 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3852 err_code |= ERR_WARN;
3853
3854 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3855 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3856 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3857 }
3858 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3859 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3860 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3861 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003862 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3863 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3864 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3865 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003866 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003867 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
3870 }
3871 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003872 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003874 char *rport, *raddr;
3875 short realport = 0;
3876 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003878 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003883 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885
3886 if (!*args[2]) {
3887 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3888 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003889 err_code |= ERR_ALERT | ERR_FATAL;
3890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003892
3893 err = invalid_char(args[1]);
3894 if (err) {
3895 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3896 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003899 }
3900
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003901 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003902 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003903
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003904 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3905 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3906 err_code |= ERR_ALERT | ERR_ABORT;
3907 goto out;
3908 }
3909
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003910 /* the servers are linked backwards first */
3911 newsrv->next = curproxy->srv;
3912 curproxy->srv = newsrv;
3913 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02003914 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003915 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003916
Simon Hormanaf514952011-06-21 14:34:57 +09003917 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003918 LIST_INIT(&newsrv->pendconns);
3919 do_check = 0;
3920 newsrv->state = SRV_RUNNING; /* early server setup */
3921 newsrv->last_change = now.tv_sec;
3922 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003924 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003925 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003926 * - IP: => port=+0, relative
3927 * - IP:N => port=N, absolute
3928 * - IP:+N => port=+N, relative
3929 * - IP:-N => port=-N, relative
3930 */
3931 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003932 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003933 if (rport) {
3934 *rport++ = 0;
3935 realport = atol(rport);
3936 if (!isdigit((unsigned char)*rport))
3937 newsrv->state |= SRV_MAPPORTS;
3938 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003940
Willy Tarreaufab5a432011-03-04 15:31:53 +01003941 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003942 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003943 if (!sk) {
3944 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
3948 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02003949 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
3950 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02003951
Willy Tarreau173e7fb2012-09-24 22:47:39 +02003952 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02003953 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
3954 file, linenum, newsrv->addr.ss_family, args[2]);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003958 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003959
Willy Tarreauf4288ee2012-09-28 18:13:10 +02003960 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02003961 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003962 newsrv->inter = curproxy->defsrv.inter;
3963 newsrv->fastinter = curproxy->defsrv.fastinter;
3964 newsrv->downinter = curproxy->defsrv.downinter;
3965 newsrv->rise = curproxy->defsrv.rise;
3966 newsrv->fall = curproxy->defsrv.fall;
3967 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3968 newsrv->minconn = curproxy->defsrv.minconn;
3969 newsrv->maxconn = curproxy->defsrv.maxconn;
3970 newsrv->slowstart = curproxy->defsrv.slowstart;
3971 newsrv->onerror = curproxy->defsrv.onerror;
3972 newsrv->consecutive_errors_limit
3973 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02003974#ifdef OPENSSL
3975 newsrv->use_ssl = curproxy->defsrv.use_ssl;
3976#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003977 newsrv->uweight = newsrv->iweight
3978 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003980 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003982 cur_arg = 3;
3983 } else {
3984 newsrv = &curproxy->defsrv;
3985 cur_arg = 1;
3986 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003987
Willy Tarreaubaaee002006-06-26 02:48:02 +02003988 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003989 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003990 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003991
3992 if (!*args[cur_arg + 1]) {
3993 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3994 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003997 }
3998
3999 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004000 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004001
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004002 if (newsrv->puid <= 0) {
4003 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004004 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004007 }
4008
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004009 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4010 if (node) {
4011 struct server *target = container_of(node, struct server, conf.id);
4012 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4013 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
4016 }
4017 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004018 cur_arg += 2;
4019 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004020 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 newsrv->cookie = strdup(args[cur_arg + 1]);
4022 newsrv->cklen = strlen(args[cur_arg + 1]);
4023 cur_arg += 2;
4024 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004025 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004026 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4027 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4028 cur_arg += 2;
4029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004031 if (!*args[cur_arg + 1]) {
4032 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4033 file, linenum, args[cur_arg]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
4036 }
4037
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004039 if (newsrv->rise <= 0) {
4040 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4041 file, linenum, args[cur_arg]);
4042 err_code |= ERR_ALERT | ERR_FATAL;
4043 goto out;
4044 }
4045
Willy Tarreau96839092010-03-29 10:02:24 +02004046 if (newsrv->health)
4047 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048 cur_arg += 2;
4049 }
4050 else if (!strcmp(args[cur_arg], "fall")) {
4051 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004052
4053 if (!*args[cur_arg + 1]) {
4054 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4055 file, linenum, args[cur_arg]);
4056 err_code |= ERR_ALERT | ERR_FATAL;
4057 goto out;
4058 }
4059
4060 if (newsrv->fall <= 0) {
4061 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4062 file, linenum, args[cur_arg]);
4063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
4065 }
4066
Willy Tarreaubaaee002006-06-26 02:48:02 +02004067 cur_arg += 2;
4068 }
4069 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004070 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4071 if (err) {
4072 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4073 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004076 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004077 if (val <= 0) {
4078 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4079 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004082 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004083 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004084 cur_arg += 2;
4085 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004086 else if (!strcmp(args[cur_arg], "fastinter")) {
4087 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4088 if (err) {
4089 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4090 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004093 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004094 if (val <= 0) {
4095 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4096 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004099 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004100 newsrv->fastinter = val;
4101 cur_arg += 2;
4102 }
4103 else if (!strcmp(args[cur_arg], "downinter")) {
4104 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4105 if (err) {
4106 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4107 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004110 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004111 if (val <= 0) {
4112 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4113 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004116 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004117 newsrv->downinter = val;
4118 cur_arg += 2;
4119 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004120 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004121 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004122 if (!sk) {
4123 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
4126 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004127 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004128 cur_arg += 2;
4129 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004130 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004131 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 cur_arg += 2;
4133 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004134 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004135 newsrv->state |= SRV_BACKUP;
4136 cur_arg ++;
4137 }
Simon Hormanfa461682011-06-25 09:39:49 +09004138 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4139 newsrv->state |= SRV_NON_STICK;
4140 cur_arg ++;
4141 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004142 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4143 newsrv->state |= SRV_SEND_PROXY;
4144 cur_arg ++;
4145 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004146 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4147 newsrv->check.send_proxy = 1;
4148 cur_arg ++;
4149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 else if (!strcmp(args[cur_arg], "weight")) {
4151 int w;
4152 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004153 if (w < 0 || w > 256) {
4154 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004159 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 cur_arg += 2;
4161 }
4162 else if (!strcmp(args[cur_arg], "minconn")) {
4163 newsrv->minconn = atol(args[cur_arg + 1]);
4164 cur_arg += 2;
4165 }
4166 else if (!strcmp(args[cur_arg], "maxconn")) {
4167 newsrv->maxconn = atol(args[cur_arg + 1]);
4168 cur_arg += 2;
4169 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004170 else if (!strcmp(args[cur_arg], "maxqueue")) {
4171 newsrv->maxqueue = atol(args[cur_arg + 1]);
4172 cur_arg += 2;
4173 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004174 else if (!strcmp(args[cur_arg], "slowstart")) {
4175 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004176 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004177 if (err) {
4178 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4179 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004182 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004183 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004184 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4185 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004188 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004189 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004190 cur_arg += 2;
4191 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004192 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004193
4194 if (!*args[cur_arg + 1]) {
4195 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4196 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004199 }
4200
4201 newsrv->trackit = strdup(args[cur_arg + 1]);
4202
4203 cur_arg += 2;
4204 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004205 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206 global.maxsock++;
4207 do_check = 1;
4208 cur_arg += 1;
4209 }
Willy Tarreau96839092010-03-29 10:02:24 +02004210 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4211 newsrv->state |= SRV_MAINTAIN;
4212 newsrv->state &= ~SRV_RUNNING;
4213 newsrv->health = 0;
4214 cur_arg += 1;
4215 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004216 else if (!strcmp(args[cur_arg], "ssl")) {
4217#ifdef USE_OPENSSL
4218 newsrv->use_ssl = 1;
4219 cur_arg += 1;
4220#else /* USE_OPENSSL */
4221 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4222 file, linenum, args[cur_arg]);
4223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
4225#endif /* USE_OPENSSL */
4226 }
Willy Tarreau763a95b2012-10-04 23:15:39 +02004227 else if (!strcmp(args[cur_arg], "check-ssl")) {
4228#ifdef USE_OPENSSL
4229 newsrv->check.use_ssl = 1;
4230 cur_arg += 1;
4231#else /* USE_OPENSSL */
4232 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4233 file, linenum, args[cur_arg]);
4234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
4236#endif /* USE_OPENSSL */
4237 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004238 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4239#ifdef USE_OPENSSL
4240 if (!*args[cur_arg + 1]) {
4241 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4242 file, linenum, args[0], args[cur_arg]);
4243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
4245 }
4246
4247 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4248
4249 cur_arg += 2;
4250 continue;
4251#else
4252 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4253 file, linenum, args[0], args[cur_arg]);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256#endif
4257 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004258 else if (!strcmp(args[cur_arg], "nosslv3")) {
4259#ifdef USE_OPENSSL
4260 newsrv->ssl_ctx.nosslv3 = 1;
4261 cur_arg += 1;
4262#else /* USE_OPENSSL */
4263 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4264 file, linenum, args[cur_arg]);
4265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
4267#endif /* USE_OPENSSL */
4268 }
Emeric Brunc0ff4922012-09-28 19:37:02 +02004269 else if (!strcmp(args[cur_arg], "notlsv10")) {
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004270#ifdef USE_OPENSSL
Emeric Brunc0ff4922012-09-28 19:37:02 +02004271 newsrv->ssl_ctx.notlsv10 = 1;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004272 cur_arg += 1;
4273#else /* USE_OPENSSL */
4274 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4275 file, linenum, args[cur_arg]);
4276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278#endif /* USE_OPENSSL */
4279 }
Emeric Brunc0ff4922012-09-28 19:37:02 +02004280 else if (!strcmp(args[cur_arg], "notlsv11")) {
4281#ifdef USE_OPENSSL
4282 newsrv->ssl_ctx.notlsv11 = 1;
4283 cur_arg += 1;
4284#else /* USE_OPENSSL */
4285 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4286 file, linenum, args[cur_arg]);
4287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
4289#endif /* USE_OPENSSL */
4290 }
4291 else if (!strcmp(args[cur_arg], "notlsv12")) {
4292#ifdef USE_OPENSSL
4293 newsrv->ssl_ctx.notlsv12 = 1;
4294 cur_arg += 1;
4295#else /* USE_OPENSSL */
4296 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4297 file, linenum, args[cur_arg]);
4298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
4300#endif /* USE_OPENSSL */
4301 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004302 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004303 if (!strcmp(args[cur_arg + 1], "none"))
4304 newsrv->observe = HANA_OBS_NONE;
4305 else if (!strcmp(args[cur_arg + 1], "layer4"))
4306 newsrv->observe = HANA_OBS_LAYER4;
4307 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4308 if (curproxy->mode != PR_MODE_HTTP) {
4309 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4310 file, linenum, args[cur_arg + 1]);
4311 err_code |= ERR_ALERT;
4312 }
4313 newsrv->observe = HANA_OBS_LAYER7;
4314 }
4315 else {
4316 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004317 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004318 file, linenum, args[cur_arg], args[cur_arg + 1]);
4319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
4321 }
4322
4323 cur_arg += 2;
4324 }
4325 else if (!strcmp(args[cur_arg], "on-error")) {
4326 if (!strcmp(args[cur_arg + 1], "fastinter"))
4327 newsrv->onerror = HANA_ONERR_FASTINTER;
4328 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4329 newsrv->onerror = HANA_ONERR_FAILCHK;
4330 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4331 newsrv->onerror = HANA_ONERR_SUDDTH;
4332 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4333 newsrv->onerror = HANA_ONERR_MARKDWN;
4334 else {
4335 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004336 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004337 file, linenum, args[cur_arg], args[cur_arg + 1]);
4338 err_code |= ERR_ALERT | ERR_FATAL;
4339 goto out;
4340 }
4341
4342 cur_arg += 2;
4343 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004344 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4345 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4346 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4347 else {
4348 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4349 file, linenum, args[cur_arg], args[cur_arg + 1]);
4350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
4352 }
4353
4354 cur_arg += 2;
4355 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004356 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4357 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4358 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4359 else {
4360 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4361 file, linenum, args[cur_arg], args[cur_arg + 1]);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
4365
4366 cur_arg += 2;
4367 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004368 else if (!strcmp(args[cur_arg], "error-limit")) {
4369 if (!*args[cur_arg + 1]) {
4370 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4371 file, linenum, args[cur_arg]);
4372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
4374 }
4375
4376 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4377
4378 if (newsrv->consecutive_errors_limit <= 0) {
4379 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4380 file, linenum, args[cur_arg]);
4381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
4383 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004384 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004385 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004386 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004387 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004388 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004389
Willy Tarreaubaaee002006-06-26 02:48:02 +02004390 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004391#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004392 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004393 file, linenum, "source", "usesrc");
4394#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004395 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004397#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004400 }
4401 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004402 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4403 if (!sk) {
4404 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
4407 }
4408 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004409
4410 if (port_low != port_high) {
4411 int i;
4412 if (port_low <= 0 || port_low > 65535 ||
4413 port_high <= 0 || port_high > 65535 ||
4414 port_low > port_high) {
4415 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4416 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004419 }
4420 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4421 for (i = 0; i < newsrv->sport_range->size; i++)
4422 newsrv->sport_range->ports[i] = port_low + i;
4423 }
4424
Willy Tarreaubaaee002006-06-26 02:48:02 +02004425 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004426 while (*(args[cur_arg])) {
4427 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004428#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4429#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004430 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4431 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4432 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004435 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004436#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004437 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004438 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004439 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004442 }
4443 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004444 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004445 newsrv->state |= SRV_TPROXY_CLI;
4446 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004447 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004448 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004449 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4450 char *name, *end;
4451
4452 name = args[cur_arg+1] + 7;
4453 while (isspace(*name))
4454 name++;
4455
4456 end = name;
4457 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4458 end++;
4459
4460 newsrv->state &= ~SRV_TPROXY_MASK;
4461 newsrv->state |= SRV_TPROXY_DYN;
4462 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4463 newsrv->bind_hdr_len = end - name;
4464 memcpy(newsrv->bind_hdr_name, name, end - name);
4465 newsrv->bind_hdr_name[end-name] = '\0';
4466 newsrv->bind_hdr_occ = -1;
4467
4468 /* now look for an occurrence number */
4469 while (isspace(*end))
4470 end++;
4471 if (*end == ',') {
4472 end++;
4473 name = end;
4474 if (*end == '-')
4475 end++;
4476 while (isdigit(*end))
4477 end++;
4478 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4479 }
4480
4481 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4482 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4483 " occurrences values smaller than %d.\n",
4484 file, linenum, MAX_HDR_HISTORY);
4485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
4487 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004488 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004489 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004490 if (!sk) {
4491 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4492 err_code |= ERR_ALERT | ERR_FATAL;
4493 goto out;
4494 }
4495 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004496 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004497 }
4498 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004499#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004500 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004501#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004502 cur_arg += 2;
4503 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004504#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004505 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004506 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004509#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4510 } /* "usesrc" */
4511
4512 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4513#ifdef SO_BINDTODEVICE
4514 if (!*args[cur_arg + 1]) {
4515 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4516 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004517 err_code |= ERR_ALERT | ERR_FATAL;
4518 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004519 }
4520 if (newsrv->iface_name)
4521 free(newsrv->iface_name);
4522
4523 newsrv->iface_name = strdup(args[cur_arg + 1]);
4524 newsrv->iface_len = strlen(newsrv->iface_name);
4525 global.last_checks |= LSTCHK_NETADM;
4526#else
4527 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4528 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004531#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004532 cur_arg += 2;
4533 continue;
4534 }
4535 /* this keyword in not an option of "source" */
4536 break;
4537 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004538 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004539 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004540 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4541 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004544 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004545 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004546 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004547 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'on-marked-down', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004548 file, linenum, newsrv->id);
4549 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004550 Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004551 file, linenum);
4552
Willy Tarreau93893792009-07-23 13:19:11 +02004553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004555 }
4556 }
4557
4558 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004559 if (newsrv->trackit) {
4560 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4561 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004564 }
4565
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004566 /* If neither a port nor an addr was specified and no check transport
4567 * layer is forced, then the transport layer used by the checks is the
4568 * same as for the production traffic. Otherwise we use raw_sock by
4569 * default, unless one is specified.
4570 */
Baptiste Assmanne6baecf2012-10-05 11:48:04 +02004571#ifdef USE_OPENSSL
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004572 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004573 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004574 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4575 }
Baptiste Assmanne6baecf2012-10-05 11:48:04 +02004576#endif
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004577 /* try to get the port from check.addr if check.port not set */
4578 if (!newsrv->check.port)
4579 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004580
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004581 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4582 newsrv->check.port = realport; /* by default */
4583 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004584 /* not yet valid, because no port was set on
4585 * the server either. We'll check if we have
4586 * a known port on the first listener.
4587 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004588 struct listener *l;
4589
4590 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004591 newsrv->check.port = get_host_port(&l->addr);
4592 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004593 break;
4594 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004595 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004596 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004597 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4598 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004601 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004602
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004603 /* Allocate buffer for check requests... */
4604 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004605 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4606 err_code |= ERR_ALERT | ERR_ABORT;
4607 goto out;
4608 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004609 newsrv->check.bi->size = global.tune.chksize;
4610
4611 /* Allocate buffer for check responses... */
4612 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4613 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4614 err_code |= ERR_ALERT | ERR_ABORT;
4615 goto out;
4616 }
4617 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004618
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004619 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004620 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004621 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4622 err_code |= ERR_ALERT | ERR_ABORT;
4623 goto out;
4624 }
4625
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004626 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4627 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628 newsrv->state |= SRV_CHECKED;
4629 }
4630
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004631 if (!defsrv) {
4632 if (newsrv->state & SRV_BACKUP)
4633 curproxy->srv_bck++;
4634 else
4635 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004636
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004637 newsrv->prev_state = newsrv->state;
4638 }
William Lallemanda73203e2012-03-12 12:48:57 +01004639 }
4640
4641 else if (strcmp(args[0], "unique-id-format") == 0) {
4642 if (!*(args[1])) {
4643 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4644 err_code |= ERR_ALERT | ERR_FATAL;
4645 goto out;
4646 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004647 free(curproxy->uniqueid_format_string);
4648 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004649 }
William Lallemanda73203e2012-03-12 12:48:57 +01004650
4651 else if (strcmp(args[0], "unique-id-header") == 0) {
4652 if (!*(args[1])) {
4653 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
4656 }
4657 free(curproxy->header_unique_id);
4658 curproxy->header_unique_id = strdup(args[1]);
4659 }
4660
William Lallemand723b73a2012-02-08 16:37:49 +01004661 else if (strcmp(args[0], "log-format") == 0) {
4662 if (!*(args[1])) {
4663 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
4666 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004667
4668 if (curproxy->logformat_string != default_http_log_format &&
4669 curproxy->logformat_string != default_tcp_log_format &&
4670 curproxy->logformat_string != clf_http_log_format)
4671 free(curproxy->logformat_string);
4672 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 }
William Lallemand723b73a2012-02-08 16:37:49 +01004674
William Lallemand0f99e342011-10-12 17:50:54 +02004675 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4676 /* delete previous herited or defined syslog servers */
4677 struct logsrv *back;
4678
4679 if (*(args[1]) != 0) {
4680 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
4683 }
4684
William Lallemand723b73a2012-02-08 16:37:49 +01004685 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4686 LIST_DEL(&tmplogsrv->list);
4687 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004688 }
4689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004690 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004691 struct logsrv *logsrv;
4692
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004694 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004695 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004696 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004697 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004698 LIST_INIT(&node->list);
4699 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004701 }
4702 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004703
4704 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004705
William Lallemand0f99e342011-10-12 17:50:54 +02004706 logsrv->facility = get_log_facility(args[2]);
4707 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004709 err_code |= ERR_ALERT | ERR_FATAL;
4710 goto out;
4711
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 }
4713
William Lallemand0f99e342011-10-12 17:50:54 +02004714 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004715 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004716 logsrv->level = get_log_level(args[3]);
4717 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004719 err_code |= ERR_ALERT | ERR_FATAL;
4720 goto out;
4721
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 }
4723 }
4724
William Lallemand0f99e342011-10-12 17:50:54 +02004725 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004726 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004727 logsrv->minlvl = get_log_level(args[4]);
4728 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004729 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004730 err_code |= ERR_ALERT | ERR_FATAL;
4731 goto out;
4732
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004733 }
4734 }
4735
Robert Tsai81ae1952007-12-05 10:47:29 +01004736 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004737 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004738 if (!sk) {
4739 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004740 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
4743 }
William Lallemand0f99e342011-10-12 17:50:54 +02004744 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004745 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004746 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004747 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004748 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
4751 }
William Lallemand0f99e342011-10-12 17:50:54 +02004752 logsrv->addr = *sk;
4753 if (!get_host_port(&logsrv->addr))
4754 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 }
William Lallemand0f99e342011-10-12 17:50:54 +02004756
4757 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 }
4759 else {
4760 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4761 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004762 err_code |= ERR_ALERT | ERR_FATAL;
4763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
4765 }
4766 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004767 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004768 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004769
Willy Tarreau977b8e42006-12-29 14:19:17 +01004770 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004771 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004772
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004774 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4775 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004779
4780 /* we must first clear any optional default setting */
4781 curproxy->options &= ~PR_O_TPXY_MASK;
4782 free(curproxy->iface_name);
4783 curproxy->iface_name = NULL;
4784 curproxy->iface_len = 0;
4785
Willy Tarreaud5191e72010-02-09 20:50:45 +01004786 sk = str2sa(args[1]);
4787 if (!sk) {
4788 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
4791 }
4792 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004794
4795 cur_arg = 2;
4796 while (*(args[cur_arg])) {
4797 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004798#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4799#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004800 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4801 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4802 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004803 err_code |= ERR_ALERT | ERR_FATAL;
4804 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004805 }
4806#endif
4807 if (!*args[cur_arg + 1]) {
4808 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4809 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004812 }
4813
4814 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004815 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004816 curproxy->options |= PR_O_TPXY_CLI;
4817 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004818 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004819 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004820 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4821 char *name, *end;
4822
4823 name = args[cur_arg+1] + 7;
4824 while (isspace(*name))
4825 name++;
4826
4827 end = name;
4828 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4829 end++;
4830
4831 curproxy->options &= ~PR_O_TPXY_MASK;
4832 curproxy->options |= PR_O_TPXY_DYN;
4833 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4834 curproxy->bind_hdr_len = end - name;
4835 memcpy(curproxy->bind_hdr_name, name, end - name);
4836 curproxy->bind_hdr_name[end-name] = '\0';
4837 curproxy->bind_hdr_occ = -1;
4838
4839 /* now look for an occurrence number */
4840 while (isspace(*end))
4841 end++;
4842 if (*end == ',') {
4843 end++;
4844 name = end;
4845 if (*end == '-')
4846 end++;
4847 while (isdigit(*end))
4848 end++;
4849 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4850 }
4851
4852 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4853 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4854 " occurrences values smaller than %d.\n",
4855 file, linenum, MAX_HDR_HISTORY);
4856 err_code |= ERR_ALERT | ERR_FATAL;
4857 goto out;
4858 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004859 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004860 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004861 if (!sk) {
4862 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4863 err_code |= ERR_ALERT | ERR_FATAL;
4864 goto out;
4865 }
4866 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004867 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004868 }
4869 global.last_checks |= LSTCHK_NETADM;
4870#if !defined(CONFIG_HAP_LINUX_TPROXY)
4871 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004872#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004873#else /* no TPROXY support */
4874 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004875 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004878#endif
4879 cur_arg += 2;
4880 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004881 }
4882
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004883 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4884#ifdef SO_BINDTODEVICE
4885 if (!*args[cur_arg + 1]) {
4886 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4887 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004890 }
4891 if (curproxy->iface_name)
4892 free(curproxy->iface_name);
4893
4894 curproxy->iface_name = strdup(args[cur_arg + 1]);
4895 curproxy->iface_len = strlen(curproxy->iface_name);
4896 global.last_checks |= LSTCHK_NETADM;
4897#else
4898 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4899 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004902#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004903 cur_arg += 2;
4904 continue;
4905 }
4906 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004907 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004912 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4913 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4914 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004915 err_code |= ERR_ALERT | ERR_FATAL;
4916 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004918 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4921 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925
4926 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004927 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004928 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 }
4932 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004934 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004935 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 }
4939 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004941 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004942 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
4946 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004948 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004949 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004955 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004956 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004960 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004962 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004963 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004965 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004966 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004967 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004969 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004970 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004971 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004972 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004973 }
4974 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004976 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004977 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004979 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004983 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4984 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988
4989 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004990 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004991 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004992 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
4995 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004996 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004997 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004998 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
5002 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005003 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005004 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005005 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 }
5009 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005010 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005011 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005012 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005013 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 }
5016 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005017 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005018 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005019 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005020 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005023 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005024 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005025 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005026 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005027 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005028 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005031 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005032
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 if (curproxy == &defproxy) {
5034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005038 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 if (*(args[1]) == 0) {
5042 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005046
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005047 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005048 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5049 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5050 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
5053 }
5054 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5055 }
5056 else if (*args[2]) {
5057 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5058 file, linenum, args[0], args[2]);
5059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
5061 }
5062
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005063 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005064 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005065 wl->s = strdup(args[1]);
5066 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005067 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068 }
5069 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005070 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5072 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005076
Willy Tarreauade5ec42010-01-28 19:33:49 +01005077 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005078 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005079 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 }
5083 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005084 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005085 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005086 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005087 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 }
5090 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005091 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005092 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005093 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 }
5097 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005098 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5100 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 }
5104
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005106 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005107 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005108 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 }
5111 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005112 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005113 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005114 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005115 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005117 }
5118 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005119 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005120 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005121 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005122 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005124 }
5125 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005126 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005127
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 if (curproxy == &defproxy) {
5129 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005132 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005133 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 if (*(args[1]) == 0) {
5137 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 }
5141
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005142 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005143 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5144 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5145 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
5148 }
5149 err_code |= warnif_cond_requires_req(cond, file, linenum);
5150 }
5151 else if (*args[2]) {
5152 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5153 file, linenum, args[0], args[2]);
5154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
5156 }
5157
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005158 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005159 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005160 wl->s = strdup(args[1]);
5161 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005162 }
5163 else if (!strcmp(args[0], "errorloc") ||
5164 !strcmp(args[0], "errorloc302") ||
5165 !strcmp(args[0], "errorloc303")) { /* error location */
5166 int errnum, errlen;
5167 char *err;
5168
Willy Tarreau977b8e42006-12-29 14:19:17 +01005169 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005170 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005171
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005173 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 }
5177
5178 errnum = atol(args[1]);
5179 if (!strcmp(args[0], "errorloc303")) {
5180 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5181 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5182 } else {
5183 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5184 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5185 }
5186
Willy Tarreau0f772532006-12-23 20:51:41 +01005187 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5188 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005189 chunk_destroy(&curproxy->errmsg[rc]);
5190 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005191 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005194
5195 if (rc >= HTTP_ERR_SIZE) {
5196 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5197 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 free(err);
5199 }
5200 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005201 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5202 int errnum, errlen, fd;
5203 char *err;
5204 struct stat stat;
5205
5206 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005208
5209 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005210 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005213 }
5214
5215 fd = open(args[2], O_RDONLY);
5216 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5217 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5218 file, linenum, args[2], args[1]);
5219 if (fd >= 0)
5220 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005223 }
5224
Willy Tarreau27a674e2009-08-17 07:23:33 +02005225 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005226 errlen = stat.st_size;
5227 } else {
5228 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005229 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005230 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005231 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005232 }
5233
5234 err = malloc(errlen); /* malloc() must succeed during parsing */
5235 errnum = read(fd, err, errlen);
5236 if (errnum != errlen) {
5237 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5238 file, linenum, args[2], args[1]);
5239 close(fd);
5240 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005243 }
5244 close(fd);
5245
5246 errnum = atol(args[1]);
5247 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5248 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005249 chunk_destroy(&curproxy->errmsg[rc]);
5250 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005251 break;
5252 }
5253 }
5254
5255 if (rc >= HTTP_ERR_SIZE) {
5256 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5257 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005258 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005259 free(err);
5260 }
5261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005263 struct cfg_kw_list *kwl;
5264 int index;
5265
5266 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5267 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5268 if (kwl->kw[index].section != CFG_LISTEN)
5269 continue;
5270 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5271 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005272 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005273 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau28a47d62012-09-18 20:02:48 +02005274 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005275 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005276 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005279 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005280 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005281 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005282 err_code |= ERR_WARN;
5283 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005284 }
Willy Tarreau93893792009-07-23 13:19:11 +02005285 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005286 }
5287 }
5288 }
5289
Willy Tarreau6daf3432008-01-22 16:44:08 +01005290 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 }
Willy Tarreau93893792009-07-23 13:19:11 +02005294 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005295 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005296 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297}
5298
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005299int
5300cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5301{
5302
5303 int err_code = 0;
5304 const char *err;
5305
5306 if (!strcmp(args[0], "userlist")) { /* new userlist */
5307 struct userlist *newul;
5308
5309 if (!*args[1]) {
5310 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5311 file, linenum, args[0]);
5312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
5315
5316 err = invalid_char(args[1]);
5317 if (err) {
5318 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5319 file, linenum, *err, args[0], args[1]);
5320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
5322 }
5323
5324 for (newul = userlist; newul; newul = newul->next)
5325 if (!strcmp(newul->name, args[1])) {
5326 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5327 file, linenum, args[1]);
5328 err_code |= ERR_WARN;
5329 goto out;
5330 }
5331
5332 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5333 if (!newul) {
5334 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5335 err_code |= ERR_ALERT | ERR_ABORT;
5336 goto out;
5337 }
5338
5339 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5340 newul->name = strdup(args[1]);
5341
5342 if (!newul->groupusers | !newul->name) {
5343 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5344 err_code |= ERR_ALERT | ERR_ABORT;
5345 goto out;
5346 }
5347
5348 newul->next = userlist;
5349 userlist = newul;
5350
5351 } else if (!strcmp(args[0], "group")) { /* new group */
5352 int cur_arg, i;
5353 const char *err;
5354
5355 if (!*args[1]) {
5356 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5357 file, linenum, args[0]);
5358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
5360 }
5361
5362 err = invalid_char(args[1]);
5363 if (err) {
5364 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5365 file, linenum, *err, args[0], args[1]);
5366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368 }
5369
5370 for(i = 0; i < userlist->grpcnt; i++)
5371 if (!strcmp(userlist->groups[i], args[1])) {
5372 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5373 file, linenum, args[1], userlist->name);
5374 err_code |= ERR_ALERT;
5375 goto out;
5376 }
5377
5378 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5379 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5380 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5381 err_code |= ERR_ALERT | ERR_FATAL;
5382 goto out;
5383 }
5384
5385 cur_arg = 2;
5386
5387 while (*args[cur_arg]) {
5388 if (!strcmp(args[cur_arg], "users")) {
5389 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5390 cur_arg += 2;
5391 continue;
5392 } else {
5393 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5394 file, linenum, args[0]);
5395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
5397 }
5398 }
5399
5400 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5401 } else if (!strcmp(args[0], "user")) { /* new user */
5402 struct auth_users *newuser;
5403 int cur_arg;
5404
5405 if (!*args[1]) {
5406 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5407 file, linenum, args[0]);
5408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 }
5411
5412 for (newuser = userlist->users; newuser; newuser = newuser->next)
5413 if (!strcmp(newuser->user, args[1])) {
5414 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5415 file, linenum, args[1], userlist->name);
5416 err_code |= ERR_ALERT;
5417 goto out;
5418 }
5419
5420 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5421 if (!newuser) {
5422 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5423 err_code |= ERR_ALERT | ERR_ABORT;
5424 goto out;
5425 }
5426
5427 newuser->user = strdup(args[1]);
5428
5429 newuser->next = userlist->users;
5430 userlist->users = newuser;
5431
5432 cur_arg = 2;
5433
5434 while (*args[cur_arg]) {
5435 if (!strcmp(args[cur_arg], "password")) {
5436#ifndef CONFIG_HAP_CRYPT
5437 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5438 file, linenum);
5439 err_code |= ERR_ALERT;
5440#endif
5441 newuser->pass = strdup(args[cur_arg + 1]);
5442 cur_arg += 2;
5443 continue;
5444 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5445 newuser->pass = strdup(args[cur_arg + 1]);
5446 newuser->flags |= AU_O_INSECURE;
5447 cur_arg += 2;
5448 continue;
5449 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005450 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005451 cur_arg += 2;
5452 continue;
5453 } else {
5454 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5455 file, linenum, args[0]);
5456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
5458 }
5459 }
5460 } else {
5461 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5462 err_code |= ERR_ALERT | ERR_FATAL;
5463 }
5464
5465out:
5466 return err_code;
5467}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468
5469/*
5470 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005471 * Returns the error code, 0 if OK, or any combination of :
5472 * - ERR_ABORT: must abort ASAP
5473 * - ERR_FATAL: we can continue parsing but not start the service
5474 * - ERR_WARN: a warning has been emitted
5475 * - ERR_ALERT: an alert has been emitted
5476 * Only the two first ones can stop processing, the two others are just
5477 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005478 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005479int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005481 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482 FILE *f;
5483 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005485 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486
Willy Tarreaubaaee002006-06-26 02:48:02 +02005487 if ((f=fopen(file,"r")) == NULL)
5488 return -1;
5489
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005490 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005491 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005492 char *end;
5493 char *args[MAX_LINE_ARGS + 1];
5494 char *line = thisline;
5495
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 linenum++;
5497
5498 end = line + strlen(line);
5499
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005500 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5501 /* Check if we reached the limit and the last char is not \n.
5502 * Watch out for the last line without the terminating '\n'!
5503 */
5504 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005505 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005506 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005507 }
5508
Willy Tarreaubaaee002006-06-26 02:48:02 +02005509 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005510 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005511 line++;
5512
5513 arg = 0;
5514 args[arg] = line;
5515
5516 while (*line && arg < MAX_LINE_ARGS) {
5517 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5518 * C equivalent value. Other combinations left unchanged (eg: \1).
5519 */
5520 if (*line == '\\') {
5521 int skip = 0;
5522 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5523 *line = line[1];
5524 skip = 1;
5525 }
5526 else if (line[1] == 'r') {
5527 *line = '\r';
5528 skip = 1;
5529 }
5530 else if (line[1] == 'n') {
5531 *line = '\n';
5532 skip = 1;
5533 }
5534 else if (line[1] == 't') {
5535 *line = '\t';
5536 skip = 1;
5537 }
5538 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005539 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005540 unsigned char hex1, hex2;
5541 hex1 = toupper(line[2]) - '0';
5542 hex2 = toupper(line[3]) - '0';
5543 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5544 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5545 *line = (hex1<<4) + hex2;
5546 skip = 3;
5547 }
5548 else {
5549 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005550 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005551 }
5552 }
5553 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005554 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005555 end -= skip;
5556 }
5557 line++;
5558 }
5559 else if (*line == '#' || *line == '\n' || *line == '\r') {
5560 /* end of string, end of loop */
5561 *line = 0;
5562 break;
5563 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005564 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005565 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005566 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005567 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568 line++;
5569 args[++arg] = line;
5570 }
5571 else {
5572 line++;
5573 }
5574 }
5575
5576 /* empty line */
5577 if (!**args)
5578 continue;
5579
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005580 if (*line) {
5581 /* we had to stop due to too many args.
5582 * Let's terminate the string, print the offending part then cut the
5583 * last arg.
5584 */
5585 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5586 line++;
5587 *line = '\0';
5588
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005589 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005590 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005591 err_code |= ERR_ALERT | ERR_FATAL;
5592 args[arg] = line;
5593 }
5594
Willy Tarreau540abe42007-05-02 20:50:16 +02005595 /* zero out remaining args and ensure that at least one entry
5596 * is zeroed out.
5597 */
5598 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 args[arg] = line;
5600 }
5601
Willy Tarreau3842f002009-06-14 11:39:52 +02005602 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005603 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005604 char *tmp;
5605
Willy Tarreau3842f002009-06-14 11:39:52 +02005606 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005607 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005608 for (arg=0; *args[arg+1]; arg++)
5609 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005610 *tmp = '\0'; // fix the next arg to \0
5611 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005612 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005613 else if (!strcmp(args[0], "default")) {
5614 kwm = KWM_DEF;
5615 for (arg=0; *args[arg+1]; arg++)
5616 args[arg] = args[arg+1]; // shift args after inversion
5617 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005618
William Lallemand0f99e342011-10-12 17:50:54 +02005619 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5620 strcmp(args[0], "log") != 0) {
5621 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005622 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005623 }
5624
Willy Tarreau977b8e42006-12-29 14:19:17 +01005625 if (!strcmp(args[0], "listen") ||
5626 !strcmp(args[0], "frontend") ||
5627 !strcmp(args[0], "backend") ||
5628 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005629 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005630 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005631 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005632 cursection = strdup(args[0]);
5633 }
5634 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005636 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005637 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005638 }
5639 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005640 confsect = CFG_USERLIST;
5641 free(cursection);
5642 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005643 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005644 else if (!strcmp(args[0], "peers")) {
5645 confsect = CFG_PEERS;
5646 free(cursection);
5647 cursection = strdup(args[0]);
5648 }
5649
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 /* else it's a section keyword */
5651
5652 switch (confsect) {
5653 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005654 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 break;
5656 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005657 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005659 case CFG_USERLIST:
5660 err_code |= cfg_parse_users(file, linenum, args, kwm);
5661 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005662 case CFG_PEERS:
5663 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5664 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005666 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005667 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005669
5670 if (err_code & ERR_ABORT)
5671 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005672 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005673 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005674 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005676 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005677}
5678
Willy Tarreaubb925012009-07-23 13:36:36 +02005679/*
5680 * Returns the error code, 0 if OK, or any combination of :
5681 * - ERR_ABORT: must abort ASAP
5682 * - ERR_FATAL: we can continue parsing but not start the service
5683 * - ERR_WARN: a warning has been emitted
5684 * - ERR_ALERT: an alert has been emitted
5685 * Only the two first ones can stop processing, the two others are just
5686 * indicators.
5687 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005688int check_config_validity()
5689{
5690 int cfgerr = 0;
5691 struct proxy *curproxy = NULL;
5692 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005693 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005694 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005695 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005696 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005698 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699 /*
5700 * Now, check for the integrity of all that we have collected.
5701 */
5702
5703 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005704 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005706 /* first, we will invert the proxy list order */
5707 curproxy = NULL;
5708 while (proxy) {
5709 struct proxy *next;
5710
5711 next = proxy->next;
5712 proxy->next = curproxy;
5713 curproxy = proxy;
5714 if (!next)
5715 break;
5716 proxy = next;
5717 }
5718
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005720 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005721 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005722 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005723 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005724 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005725 unsigned int next_id;
5726
Willy Tarreau050536d2012-10-04 08:47:34 +02005727 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005728 /* proxy ID not set, use automatic numbering with first
5729 * spare entry starting with next_pxid.
5730 */
5731 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5732 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5733 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005734 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005735 next_pxid++;
5736
Willy Tarreau55ea7572007-06-17 19:56:27 +02005737
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005739 /* ensure we don't keep listeners uselessly bound */
5740 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741 curproxy = curproxy->next;
5742 continue;
5743 }
5744
Willy Tarreauff01a212009-03-15 13:46:16 +01005745 switch (curproxy->mode) {
5746 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005747 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005748 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005749 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5750 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005751 cfgerr++;
5752 }
5753
5754 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005755 Warning("config : servers will be ignored for %s '%s'.\n",
5756 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005757 break;
5758
5759 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005760 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005761 break;
5762
5763 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005764 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005765 break;
5766 }
5767
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005768 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005769 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005770 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005771 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5772 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005773 cfgerr++;
5774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005776 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005777 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5778 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005779 cfgerr++;
5780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005781#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005782 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005783 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5784 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005785 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005786 }
5787 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005788 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005789 /* If no LB algo is set in a backend, and we're not in
5790 * transparent mode, dispatch mode nor proxy mode, we
5791 * want to use balance roundrobin by default.
5792 */
5793 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5794 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 }
5796 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005797
Willy Tarreau1620ec32011-08-06 17:05:02 +02005798 if (curproxy->options & PR_O_DISPATCH)
5799 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5800 else if (curproxy->options & PR_O_HTTP_PROXY)
5801 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5802 else if (curproxy->options & PR_O_TRANSP)
5803 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005804
Willy Tarreau1620ec32011-08-06 17:05:02 +02005805 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5806 if (curproxy->options & PR_O_DISABLE404) {
5807 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5808 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5809 err_code |= ERR_WARN;
5810 curproxy->options &= ~PR_O_DISABLE404;
5811 }
5812 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5813 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5814 "send-state", proxy_type_str(curproxy), curproxy->id);
5815 err_code |= ERR_WARN;
5816 curproxy->options &= ~PR_O2_CHK_SNDST;
5817 }
Willy Tarreauef781042010-01-27 11:53:01 +01005818 }
5819
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005820 /* if a default backend was specified, let's find it */
5821 if (curproxy->defbe.name) {
5822 struct proxy *target;
5823
Alex Williams96532db2009-11-01 21:27:13 -05005824 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005825 if (!target) {
5826 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5827 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005828 cfgerr++;
5829 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005830 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5831 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005832 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005833 } else {
5834 free(curproxy->defbe.name);
5835 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005836 /* we force the backend to be present on at least all of
5837 * the frontend's processes.
5838 */
5839 target->bind_proc = curproxy->bind_proc ?
5840 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005841
5842 /* Emit a warning if this proxy also has some servers */
5843 if (curproxy->srv) {
5844 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5845 curproxy->id);
5846 err_code |= ERR_WARN;
5847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 }
5849 }
5850
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005851 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005852 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5853 /* map jump target for ACT_SETBE in req_rep chain */
5854 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005855 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005856 struct proxy *target;
5857
Willy Tarreaua496b602006-12-17 23:15:24 +01005858 if (exp->action != ACT_SETBE)
5859 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005860
Alex Williams96532db2009-11-01 21:27:13 -05005861 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005862 if (!target) {
5863 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5864 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005865 cfgerr++;
5866 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005867 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5868 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005869 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005870 } else {
5871 free((void *)exp->replace);
5872 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005873 /* we force the backend to be present on at least all of
5874 * the frontend's processes.
5875 */
5876 target->bind_proc = curproxy->bind_proc ?
5877 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005878 }
5879 }
5880 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005881
5882 /* find the target proxy for 'use_backend' rules */
5883 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005884 struct proxy *target;
5885
Alex Williams96532db2009-11-01 21:27:13 -05005886 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005887
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005888 if (!target) {
5889 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5890 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005891 cfgerr++;
5892 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005893 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5894 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005895 cfgerr++;
5896 } else {
5897 free((void *)rule->be.name);
5898 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005899 /* we force the backend to be present on at least all of
5900 * the frontend's processes.
5901 */
5902 target->bind_proc = curproxy->bind_proc ?
5903 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005904 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005905 }
5906
5907 /* find the target proxy for 'use_backend' rules */
5908 list_for_each_entry(srule, &curproxy->server_rules, list) {
5909 struct server *target = findserver(curproxy, srule->srv.name);
5910
5911 if (!target) {
5912 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5913 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5914 cfgerr++;
5915 continue;
5916 }
5917 free((void *)srule->srv.name);
5918 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005919 }
5920
Emeric Brunb982a3d2010-01-04 15:45:53 +01005921 /* find the target table for 'stick' rules */
5922 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5923 struct proxy *target;
5924
Emeric Brun1d33b292010-01-04 15:47:17 +01005925 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5926 if (mrule->flags & STK_IS_STORE)
5927 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5928
Emeric Brunb982a3d2010-01-04 15:45:53 +01005929 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005930 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005931 else
5932 target = curproxy;
5933
5934 if (!target) {
5935 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5936 curproxy->id, mrule->table.name);
5937 cfgerr++;
5938 }
5939 else if (target->table.size == 0) {
5940 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5941 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5942 cfgerr++;
5943 }
Willy Tarreau12785782012-04-27 21:37:17 +02005944 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5945 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005946 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5947 cfgerr++;
5948 }
5949 else {
5950 free((void *)mrule->table.name);
5951 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005952 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005953 }
5954 }
5955
5956 /* find the target table for 'store response' rules */
5957 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5958 struct proxy *target;
5959
Emeric Brun1d33b292010-01-04 15:47:17 +01005960 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5961
Emeric Brunb982a3d2010-01-04 15:45:53 +01005962 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005963 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005964 else
5965 target = curproxy;
5966
5967 if (!target) {
5968 Alert("Proxy '%s': unable to find store table '%s'.\n",
5969 curproxy->id, mrule->table.name);
5970 cfgerr++;
5971 }
5972 else if (target->table.size == 0) {
5973 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5974 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5975 cfgerr++;
5976 }
Willy Tarreau12785782012-04-27 21:37:17 +02005977 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5978 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005979 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5980 cfgerr++;
5981 }
5982 else {
5983 free((void *)mrule->table.name);
5984 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005985 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005986 }
5987 }
5988
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005989 /* find the target table for 'tcp-request' layer 4 rules */
5990 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5991 struct proxy *target;
5992
Willy Tarreau56123282010-08-06 19:06:56 +02005993 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005994 continue;
5995
5996 if (trule->act_prm.trk_ctr.table.n)
5997 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5998 else
5999 target = curproxy;
6000
6001 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006002 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6003 curproxy->id, trule->act_prm.trk_ctr.table.n,
6004 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006005 cfgerr++;
6006 }
6007 else if (target->table.size == 0) {
6008 Alert("Proxy '%s': table '%s' used but not configured.\n",
6009 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6010 cfgerr++;
6011 }
6012 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006013 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 +02006014 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6015 cfgerr++;
6016 }
6017 else {
6018 free(trule->act_prm.trk_ctr.table.n);
6019 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006020 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006021 * to pass a list of counters to track and allocate them right here using
6022 * stktable_alloc_data_type().
6023 */
6024 }
6025 }
6026
Willy Tarreaud1f96522010-08-03 19:34:32 +02006027 /* find the target table for 'tcp-request' layer 6 rules */
6028 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6029 struct proxy *target;
6030
Willy Tarreau56123282010-08-06 19:06:56 +02006031 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006032 continue;
6033
6034 if (trule->act_prm.trk_ctr.table.n)
6035 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6036 else
6037 target = curproxy;
6038
6039 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006040 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6041 curproxy->id, trule->act_prm.trk_ctr.table.n,
6042 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006043 cfgerr++;
6044 }
6045 else if (target->table.size == 0) {
6046 Alert("Proxy '%s': table '%s' used but not configured.\n",
6047 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6048 cfgerr++;
6049 }
6050 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006051 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 +02006052 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6053 cfgerr++;
6054 }
6055 else {
6056 free(trule->act_prm.trk_ctr.table.n);
6057 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006058 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006059 * to pass a list of counters to track and allocate them right here using
6060 * stktable_alloc_data_type().
6061 */
6062 }
6063 }
6064
Emeric Brun32da3c42010-09-23 18:39:19 +02006065 if (curproxy->table.peers.name) {
6066 struct peers *curpeers = peers;
6067
6068 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6069 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6070 free((void *)curproxy->table.peers.name);
6071 curproxy->table.peers.p = peers;
6072 break;
6073 }
6074 }
6075
6076 if (!curpeers) {
6077 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6078 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006079 free((void *)curproxy->table.peers.name);
6080 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006081 cfgerr++;
6082 }
6083 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006084 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6085 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006086 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006087 cfgerr++;
6088 }
6089 }
6090
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006091 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006092 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006093 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6094 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6095 "proxy", curproxy->id);
6096 cfgerr++;
6097 goto out_uri_auth_compat;
6098 }
6099
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006100 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006101 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006102 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006103 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006104
Willy Tarreau95fa4692010-02-01 13:05:50 +01006105 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6106 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006107
6108 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006109 uri_auth_compat_req[i++] = "realm";
6110 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6111 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006112
Willy Tarreau95fa4692010-02-01 13:05:50 +01006113 uri_auth_compat_req[i++] = "unless";
6114 uri_auth_compat_req[i++] = "{";
6115 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6116 uri_auth_compat_req[i++] = "}";
6117 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006118
Willy Tarreauff011f22011-01-06 17:51:27 +01006119 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6120 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006121 cfgerr++;
6122 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006123 }
6124
Willy Tarreauff011f22011-01-06 17:51:27 +01006125 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006126
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006127 if (curproxy->uri_auth->auth_realm) {
6128 free(curproxy->uri_auth->auth_realm);
6129 curproxy->uri_auth->auth_realm = NULL;
6130 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006131
6132 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006133 }
6134out_uri_auth_compat:
6135
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006136 cfgerr += acl_find_targets(curproxy);
6137
Willy Tarreau2738a142006-07-08 17:28:09 +02006138 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006139 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006140 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006141 (!curproxy->timeout.connect ||
6142 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006143 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006144 " | While not properly invalid, you will certainly encounter various problems\n"
6145 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006146 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006147 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006148 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006149 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006150
Willy Tarreau1fa31262007-12-03 00:36:16 +01006151 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6152 * We must still support older configurations, so let's find out whether those
6153 * parameters have been set or must be copied from contimeouts.
6154 */
6155 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006156 if (!curproxy->timeout.tarpit ||
6157 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006158 /* tarpit timeout not set. We search in the following order:
6159 * default.tarpit, curr.connect, default.connect.
6160 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006161 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006162 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006163 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006164 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006165 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006166 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006167 }
6168 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006169 (!curproxy->timeout.queue ||
6170 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006171 /* queue timeout not set. We search in the following order:
6172 * default.queue, curr.connect, default.connect.
6173 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006174 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006175 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006176 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006177 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006178 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006179 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006180 }
6181 }
6182
Willy Tarreau1620ec32011-08-06 17:05:02 +02006183 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006184 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6185 curproxy->check_req = (char *)malloc(curproxy->check_len);
6186 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006187 }
6188
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006189 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006190 if (curproxy->nb_req_cap) {
6191 if (curproxy->mode == PR_MODE_HTTP) {
6192 curproxy->req_cap_pool = create_pool("ptrcap",
6193 curproxy->nb_req_cap * sizeof(char *),
6194 MEM_F_SHARED);
6195 } else {
6196 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6197 proxy_type_str(curproxy), curproxy->id);
6198 err_code |= ERR_WARN;
6199 curproxy->to_log &= ~LW_REQHDR;
6200 curproxy->nb_req_cap = 0;
6201 }
6202 }
6203
6204 if (curproxy->nb_rsp_cap) {
6205 if (curproxy->mode == PR_MODE_HTTP) {
6206 curproxy->rsp_cap_pool = create_pool("ptrcap",
6207 curproxy->nb_rsp_cap * sizeof(char *),
6208 MEM_F_SHARED);
6209 } else {
6210 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6211 proxy_type_str(curproxy), curproxy->id);
6212 err_code |= ERR_WARN;
6213 curproxy->to_log &= ~LW_REQHDR;
6214 curproxy->nb_rsp_cap = 0;
6215 }
6216 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006217
Willy Tarreau196729e2012-05-31 19:30:26 +02006218 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006219 if (!(curproxy->cap & PR_CAP_FE)) {
6220 if (curproxy->logformat_string != default_http_log_format &&
6221 curproxy->logformat_string != default_tcp_log_format &&
6222 curproxy->logformat_string != clf_http_log_format)
6223 free(curproxy->logformat_string);
6224 curproxy->logformat_string = NULL;
6225 }
6226
Willy Tarreau196729e2012-05-31 19:30:26 +02006227 if (curproxy->logformat_string)
6228 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6229
6230 if (curproxy->uniqueid_format_string)
6231 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6232
Willy Tarreaubaaee002006-06-26 02:48:02 +02006233 /* first, we will invert the servers list order */
6234 newsrv = NULL;
6235 while (curproxy->srv) {
6236 struct server *next;
6237
6238 next = curproxy->srv->next;
6239 curproxy->srv->next = newsrv;
6240 newsrv = curproxy->srv;
6241 if (!next)
6242 break;
6243 curproxy->srv = next;
6244 }
6245
Willy Tarreaudd701652010-05-25 23:03:02 +02006246 /* assign automatic UIDs to servers which don't have one yet */
6247 next_id = 1;
6248 newsrv = curproxy->srv;
6249 while (newsrv != NULL) {
6250 if (!newsrv->puid) {
6251 /* server ID not set, use automatic numbering with first
6252 * spare entry starting with next_svid.
6253 */
6254 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6255 newsrv->conf.id.key = newsrv->puid = next_id;
6256 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6257 }
6258 next_id++;
6259 newsrv = newsrv->next;
6260 }
6261
Willy Tarreau20697042007-11-15 23:26:18 +01006262 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006263 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006264
Willy Tarreau62c3be22012-01-20 13:12:32 +01006265 /*
6266 * If this server supports a maxconn parameter, it needs a dedicated
6267 * tasks to fill the emptied slots when a connection leaves.
6268 * Also, resolve deferred tracking dependency if needed.
6269 */
6270 newsrv = curproxy->srv;
6271 while (newsrv != NULL) {
6272 if (newsrv->minconn > newsrv->maxconn) {
6273 /* Only 'minconn' was specified, or it was higher than or equal
6274 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6275 * this will avoid further useless expensive computations.
6276 */
6277 newsrv->maxconn = newsrv->minconn;
6278 } else if (newsrv->maxconn && !newsrv->minconn) {
6279 /* minconn was not specified, so we set it to maxconn */
6280 newsrv->minconn = newsrv->maxconn;
6281 }
6282
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006283#ifdef USE_OPENSSL
6284#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6285#define SSL_OP_NO_COMPRESSION 0
6286#endif
6287#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6288#define SSL_MODE_RELEASE_BUFFERS 0
6289#endif
6290#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6291#define SSL_OP_NO_COMPRESSION 0
6292#endif
Emeric Brunc0ff4922012-09-28 19:37:02 +02006293#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
6294#define SSL_OP_NO_TLSv1_1 0
6295#endif
6296#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
6297#define SSL_OP_NO_TLSv1_2 0
6298#endif
Willy Tarreauf4288ee2012-09-28 18:13:10 +02006299 if (newsrv->use_ssl || newsrv->check.use_ssl) {
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006300 int ssloptions =
6301 SSL_OP_ALL | /* all known workarounds for bugs */
6302 SSL_OP_NO_SSLv2 |
6303 SSL_OP_NO_COMPRESSION;
6304 int sslmode =
6305 SSL_MODE_ENABLE_PARTIAL_WRITE |
6306 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6307 SSL_MODE_RELEASE_BUFFERS;
6308
6309 /* Initiate SSL context for current server */
6310 newsrv->ssl_ctx.reused_sess = NULL;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02006311 if (newsrv->use_ssl)
6312 newsrv->xprt = &ssl_sock;
Willy Tarreauf1503172012-09-28 19:39:36 +02006313 if (newsrv->check.use_ssl)
6314 newsrv->check.xprt = &ssl_sock;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006315 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6316 if(!newsrv->ssl_ctx.ctx) {
6317
6318 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6319 proxy_type_str(curproxy), curproxy->id,
6320 newsrv->id);
6321 cfgerr++;
6322 goto next_srv;
6323 }
6324
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006325 if (newsrv->ssl_ctx.nosslv3)
6326 ssloptions |= SSL_OP_NO_SSLv3;
Emeric Brunc0ff4922012-09-28 19:37:02 +02006327 if (newsrv->ssl_ctx.notlsv10)
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006328 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02006329 if (newsrv->ssl_ctx.notlsv11)
6330 ssloptions |= SSL_OP_NO_TLSv1_1;
6331 if (newsrv->ssl_ctx.notlsv12)
6332 ssloptions |= SSL_OP_NO_TLSv1_2;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006333 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6334 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6335 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6336 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006337 if (newsrv->ssl_ctx.ciphers &&
6338 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6339 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6340 curproxy->id, newsrv->id,
6341 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6342 cfgerr++;
6343 goto next_srv;
6344 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006345 }
6346#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006347 if (newsrv->trackit) {
6348 struct proxy *px;
6349 struct server *srv;
6350 char *pname, *sname;
6351
6352 pname = newsrv->trackit;
6353 sname = strrchr(pname, '/');
6354
6355 if (sname)
6356 *sname++ = '\0';
6357 else {
6358 sname = pname;
6359 pname = NULL;
6360 }
6361
6362 if (pname) {
6363 px = findproxy(pname, PR_CAP_BE);
6364 if (!px) {
6365 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6366 proxy_type_str(curproxy), curproxy->id,
6367 newsrv->id, pname);
6368 cfgerr++;
6369 goto next_srv;
6370 }
6371 } else
6372 px = curproxy;
6373
6374 srv = findserver(px, sname);
6375 if (!srv) {
6376 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6377 proxy_type_str(curproxy), curproxy->id,
6378 newsrv->id, sname);
6379 cfgerr++;
6380 goto next_srv;
6381 }
6382
6383 if (!(srv->state & SRV_CHECKED)) {
6384 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6385 "tracking as it does not have checks enabled.\n",
6386 proxy_type_str(curproxy), curproxy->id,
6387 newsrv->id, px->id, srv->id);
6388 cfgerr++;
6389 goto next_srv;
6390 }
6391
6392 if (curproxy != px &&
6393 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6394 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6395 "tracking: disable-on-404 option inconsistency.\n",
6396 proxy_type_str(curproxy), curproxy->id,
6397 newsrv->id, px->id, srv->id);
6398 cfgerr++;
6399 goto next_srv;
6400 }
6401
6402 /* if the other server is forced disabled, we have to do the same here */
6403 if (srv->state & SRV_MAINTAIN) {
6404 newsrv->state |= SRV_MAINTAIN;
6405 newsrv->state &= ~SRV_RUNNING;
6406 newsrv->health = 0;
6407 }
6408
6409 newsrv->track = srv;
6410 newsrv->tracknext = srv->tracknext;
6411 srv->tracknext = newsrv;
6412
6413 free(newsrv->trackit);
6414 newsrv->trackit = NULL;
6415 }
6416 next_srv:
6417 newsrv = newsrv->next;
6418 }
6419
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006420 /* We have to initialize the server lookup mechanism depending
6421 * on what LB algorithm was choosen.
6422 */
6423
6424 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6425 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6426 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006427 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6428 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6429 init_server_map(curproxy);
6430 } else {
6431 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6432 fwrr_init_server_groups(curproxy);
6433 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006434 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006435
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006436 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006437 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6438 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6439 fwlc_init_server_tree(curproxy);
6440 } else {
6441 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6442 fas_init_server_tree(curproxy);
6443 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006444 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006445
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006446 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006447 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6448 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6449 chash_init_server_tree(curproxy);
6450 } else {
6451 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6452 init_server_map(curproxy);
6453 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006454 break;
6455 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456
6457 if (curproxy->options & PR_O_LOGASAP)
6458 curproxy->to_log &= ~LW_BYTES;
6459
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006460 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006461 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006462 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6463 proxy_type_str(curproxy), curproxy->id);
6464 err_code |= ERR_WARN;
6465 }
6466
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006467 if (curproxy->mode != PR_MODE_HTTP) {
6468 int optnum;
6469
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006470 if (curproxy->uri_auth) {
6471 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6472 proxy_type_str(curproxy), curproxy->id);
6473 err_code |= ERR_WARN;
6474 curproxy->uri_auth = NULL;
6475 }
6476
Willy Tarreau87cf5142011-08-19 22:57:24 +02006477 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006478 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6479 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6480 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006481 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006482 }
6483
6484 if (curproxy->options & PR_O_ORGTO) {
6485 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6486 "originalto", proxy_type_str(curproxy), curproxy->id);
6487 err_code |= ERR_WARN;
6488 curproxy->options &= ~PR_O_ORGTO;
6489 }
6490
6491 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6492 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6493 (curproxy->cap & cfg_opts[optnum].cap) &&
6494 (curproxy->options & cfg_opts[optnum].val)) {
6495 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6496 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6497 err_code |= ERR_WARN;
6498 curproxy->options &= ~cfg_opts[optnum].val;
6499 }
6500 }
6501
6502 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6503 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6504 (curproxy->cap & cfg_opts2[optnum].cap) &&
6505 (curproxy->options2 & cfg_opts2[optnum].val)) {
6506 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6507 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6508 err_code |= ERR_WARN;
6509 curproxy->options2 &= ~cfg_opts2[optnum].val;
6510 }
6511 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006512
Willy Tarreauefa5f512010-03-30 20:13:29 +02006513#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006514 if (curproxy->bind_hdr_occ) {
6515 curproxy->bind_hdr_occ = 0;
6516 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6517 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6518 err_code |= ERR_WARN;
6519 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006520#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006521 }
6522
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006524 * ensure that we're not cross-dressing a TCP server into HTTP.
6525 */
6526 newsrv = curproxy->srv;
6527 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006528 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006529 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6530 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006531 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006532 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006533
Willy Tarreau0cec3312011-10-31 13:49:26 +01006534 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6535 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6536 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6537 err_code |= ERR_WARN;
6538 }
6539
Willy Tarreauefa5f512010-03-30 20:13:29 +02006540#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006541 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6542 newsrv->bind_hdr_occ = 0;
6543 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6544 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6545 err_code |= ERR_WARN;
6546 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006547#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006548 newsrv = newsrv->next;
6549 }
6550
Willy Tarreauc1a21672009-08-16 22:37:44 +02006551 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006552 if (!curproxy->accept)
6553 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006554
Willy Tarreauc1a21672009-08-16 22:37:44 +02006555 if (curproxy->tcp_req.inspect_delay ||
6556 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006557 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006558
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006559 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006560 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006561 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006562 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006563
6564 /* both TCP and HTTP must check switching rules */
6565 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6566 }
6567
6568 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006569 if (curproxy->tcp_req.inspect_delay ||
6570 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6571 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6572
Emeric Brun97679e72010-09-23 17:56:44 +02006573 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6574 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6575
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006576 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006577 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006578 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006579 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006580
6581 /* If the backend does requires RDP cookie persistence, we have to
6582 * enable the corresponding analyser.
6583 */
6584 if (curproxy->options2 & PR_O2_RDPC_PRST)
6585 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6586 }
6587
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006588 /* Configure SSL for each bind line.
6589 * Note: if configuration fails at some point, the ->ctx member
6590 * remains NULL so that listeners can later detach.
6591 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006592 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6593 if (!bind_conf->is_ssl)
6594 continue;
6595#ifdef USE_OPENSSL
6596 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006597 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006598 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006599 cfgerr++;
6600 continue;
6601 }
6602
Emeric Brun4b3091e2012-09-24 15:48:52 +02006603 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006604 Alert("Unable to allocate SSL session cache.\n");
6605 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006606 continue;
6607 }
6608
Emeric Brunfc0421f2012-09-07 17:30:07 +02006609 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006610 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006611#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006612 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006613
Willy Tarreaue6b98942007-10-29 01:09:36 +01006614 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006615 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006616 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006617 if (!listener->luid) {
6618 /* listener ID not set, use automatic numbering with first
6619 * spare entry starting with next_luid.
6620 */
6621 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6622 listener->conf.id.key = listener->luid = next_id;
6623 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006624 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006625 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006626
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006627 /* enable separate counters */
6628 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6629 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6630 if (!listener->name) {
6631 sprintf(trash, "sock-%d", listener->luid);
6632 listener->name = strdup(trash);
6633 }
6634 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006635
Willy Tarreaue6b98942007-10-29 01:09:36 +01006636 if (curproxy->options & PR_O_TCP_NOLING)
6637 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006638 if (!listener->maxconn)
6639 listener->maxconn = curproxy->maxconn;
6640 if (!listener->backlog)
6641 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006642 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006643 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006644 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006645 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006646
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006647 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6648 listener->options |= LI_O_TCP_RULES;
6649
Willy Tarreaude3041d2010-05-31 10:56:17 +02006650 if (curproxy->mon_mask.s_addr)
6651 listener->options |= LI_O_CHK_MONNET;
6652
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006653 /* smart accept mode is automatic in HTTP mode */
6654 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006655 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006656 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6657 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006658 }
6659
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006660 /* Release unused SSL configs */
6661 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6662 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006663 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006664#ifdef USE_OPENSSL
6665 ssl_sock_free_all_ctx(bind_conf);
Emeric Brund94b3fe2012-09-20 18:23:56 +02006666 free(bind_conf->cafile);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006667 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006668 free(bind_conf->ecdhe);
Emeric Brund94b3fe2012-09-20 18:23:56 +02006669 free(bind_conf->crlfile);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006670#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006671 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006672
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006673 /* Check multi-process mode compatibility for the current proxy */
6674 if (global.nbproc > 1) {
6675 int nbproc = 0;
6676 if (curproxy->bind_proc) {
6677 int proc;
6678 for (proc = 0; proc < global.nbproc; proc++) {
6679 if (curproxy->bind_proc & (1 << proc)) {
6680 nbproc++;
6681 }
6682 }
6683 } else {
6684 nbproc = global.nbproc;
6685 }
6686 if (curproxy->table.peers.name) {
6687 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6688 curproxy->id);
6689 cfgerr++;
6690 }
6691 if (nbproc > 1) {
6692 if (curproxy->uri_auth) {
6693 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6694 curproxy->id);
6695 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6696 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6697 curproxy->id);
6698 }
6699 }
6700 if (curproxy->appsession_name) {
6701 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6702 curproxy->id);
6703 }
6704 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6705 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6706 curproxy->id);
6707 }
6708 }
6709 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006710
6711 /* create the task associated with the proxy */
6712 curproxy->task = task_new();
6713 if (curproxy->task) {
6714 curproxy->task->context = curproxy;
6715 curproxy->task->process = manage_proxy;
6716 /* no need to queue, it will be done automatically if some
6717 * listener gets limited.
6718 */
6719 curproxy->task->expire = TICK_ETERNITY;
6720 } else {
6721 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6722 curproxy->id);
6723 cfgerr++;
6724 }
6725
Willy Tarreaubaaee002006-06-26 02:48:02 +02006726 curproxy = curproxy->next;
6727 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006728
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006729 /* Check multi-process mode compatibility */
6730 if (global.nbproc > 1) {
6731 if (global.stats_fe) {
6732 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6733 }
6734 }
6735
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006736 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6737 struct auth_users *curuser;
6738 int g;
6739
6740 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6741 unsigned int group_mask = 0;
6742 char *group = NULL;
6743
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006744 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006745 continue;
6746
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006747 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006748
6749 for (g = 0; g < curuserlist->grpcnt; g++)
6750 if (!strcmp(curuserlist->groups[g], group))
6751 break;
6752
6753 if (g == curuserlist->grpcnt) {
6754 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6755 curuserlist->name, group, curuser->user);
6756 err_code |= ERR_ALERT | ERR_FATAL;
6757 goto out;
6758 }
6759
6760 group_mask |= (1 << g);
6761 }
6762
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006763 free(curuser->u.groups);
6764 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006765 }
6766
6767 for (g = 0; g < curuserlist->grpcnt; g++) {
6768 char *user = NULL;
6769
6770 if (!curuserlist->groupusers[g])
6771 continue;
6772
6773 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6774 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6775 if (!strcmp(curuser->user, user))
6776 break;
6777
6778 if (!curuser) {
6779 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6780 curuserlist->name, user, curuserlist->groups[g]);
6781 err_code |= ERR_ALERT | ERR_FATAL;
6782 goto out;
6783 }
6784
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006785 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006786 }
6787
6788 free(curuserlist->groupusers[g]);
6789 }
6790
6791 free(curuserlist->groupusers);
6792
6793#ifdef DEBUG_AUTH
6794 for (g = 0; g < curuserlist->grpcnt; g++) {
6795 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6796
6797 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006798 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006799 fprintf(stderr, " %s", curuser->user);
6800 }
6801
6802 fprintf(stderr, "\n");
6803 }
6804#endif
6805
Willy Tarreaufbb78422011-06-05 15:38:35 +02006806 }
6807
6808 /* automatically compute fullconn if not set. We must not do it in the
6809 * loop above because cross-references are not yet fully resolved.
6810 */
6811 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6812 /* If <fullconn> is not set, let's set it to 10% of the sum of
6813 * the possible incoming frontend's maxconns.
6814 */
6815 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6816 struct proxy *fe;
6817 int total = 0;
6818
6819 /* sum up the number of maxconns of frontends which
6820 * reference this backend at least once or which are
6821 * the same one ('listen').
6822 */
6823 for (fe = proxy; fe; fe = fe->next) {
6824 struct switching_rule *rule;
6825 struct hdr_exp *exp;
6826 int found = 0;
6827
6828 if (!(fe->cap & PR_CAP_FE))
6829 continue;
6830
6831 if (fe == curproxy) /* we're on a "listen" instance */
6832 found = 1;
6833
6834 if (fe->defbe.be == curproxy) /* "default_backend" */
6835 found = 1;
6836
6837 /* check if a "use_backend" rule matches */
6838 if (!found) {
6839 list_for_each_entry(rule, &fe->switching_rules, list) {
6840 if (rule->be.backend == curproxy) {
6841 found = 1;
6842 break;
6843 }
6844 }
6845 }
6846
6847 /* check if a "reqsetbe" rule matches */
6848 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6849 if (exp->action == ACT_SETBE &&
6850 (struct proxy *)exp->replace == curproxy) {
6851 found = 1;
6852 break;
6853 }
6854 }
6855
6856 /* now we've checked all possible ways to reference a backend
6857 * from a frontend.
6858 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006859 if (!found)
6860 continue;
6861 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006862 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006863 /* we have the sum of the maxconns in <total>. We only
6864 * keep 10% of that sum to set the default fullconn, with
6865 * a hard minimum of 1 (to avoid a divide by zero).
6866 */
6867 curproxy->fullconn = (total + 9) / 10;
6868 if (!curproxy->fullconn)
6869 curproxy->fullconn = 1;
6870 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006871 }
6872
Willy Tarreau056f5682010-06-06 15:51:11 +02006873 /* initialize stick-tables on backend capable proxies. This must not
6874 * be done earlier because the data size may be discovered while parsing
6875 * other proxies.
6876 */
6877 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006878 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006879
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006880 /*
6881 * Recount currently required checks.
6882 */
6883
6884 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6885 int optnum;
6886
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006887 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6888 if (curproxy->options & cfg_opts[optnum].val)
6889 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006890
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006891 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6892 if (curproxy->options2 & cfg_opts2[optnum].val)
6893 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006894 }
6895
Willy Tarreau122541c2011-09-07 21:24:49 +02006896 if (peers) {
6897 struct peers *curpeers = peers, **last;
6898 struct peer *p, *pb;
6899
6900 /* Remove all peers sections which don't have a valid listener.
6901 * This can happen when a peers section is never referenced and
6902 * does not contain a local peer.
6903 */
6904 last = &peers;
6905 while (*last) {
6906 curpeers = *last;
6907 if (curpeers->peers_fe) {
6908 last = &curpeers->next;
6909 continue;
6910 }
6911
6912 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6913 curpeers->id, localpeer);
6914
6915 p = curpeers->remote;
6916 while (p) {
6917 pb = p->next;
6918 free(p->id);
6919 free(p);
6920 p = pb;
6921 }
6922
6923 /* Destroy and unlink this curpeers section.
6924 * Note: curpeers is backed up into *last.
6925 */
6926 free(curpeers->id);
6927 curpeers = curpeers->next;
6928 free(*last);
6929 *last = curpeers;
6930 }
6931 }
6932
Willy Tarreauac1932d2011-10-24 19:14:41 +02006933 if (!global.tune.max_http_hdr)
6934 global.tune.max_http_hdr = MAX_HTTP_HDR;
6935
Willy Tarreau34eb6712011-10-24 18:15:04 +02006936 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006937 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006938 MEM_F_SHARED);
6939
Willy Tarreaubb925012009-07-23 13:36:36 +02006940 if (cfgerr > 0)
6941 err_code |= ERR_ALERT | ERR_FATAL;
6942 out:
6943 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006944}
6945
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006946/*
6947 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6948 * parsing sessions.
6949 */
6950void cfg_register_keywords(struct cfg_kw_list *kwl)
6951{
6952 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6953}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006954
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006955/*
6956 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6957 */
6958void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6959{
6960 LIST_DEL(&kwl->list);
6961 LIST_INIT(&kwl->list);
6962}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006963
6964/*
6965 * Local variables:
6966 * c-indent-level: 8
6967 * c-basic-offset: 8
6968 * End:
6969 */