blob: 315e5ed3d9505c4765efd3843d3bc62babc04c85 [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>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int 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 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
209 struct sockaddr_storage ss;
210
211 str = next;
212 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100213 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 *next++ = 0;
215 }
216
Emeric Bruned760922010-10-22 17:59:25 +0200217 if (*str == '/') {
218 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
219 /* so compute max path */
220 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
221 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 +0200222
Emeric Bruned760922010-10-22 17:59:25 +0200223 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200225 goto fail;
226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200229 ss.ss_family = AF_UNIX;
230 if (global.unix_bind.prefix) {
231 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
232 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 }
Emeric Bruned760922010-10-22 17:59:25 +0200234 else {
235 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
236 }
237 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 }
239 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100240 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 ss2 = str2sa_range(str, &port, &end);
243 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 if (!port) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100253 /* OK the address looks correct */
254 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
Emeric Bruned760922010-10-22 17:59:25 +0200256 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200257 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
260
261 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
266
267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100269 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200270 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
271 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
272 l->frontend = curproxy;
273 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
275 l->fd = -1;
276 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200277 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 l->state = LI_INIT;
279
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100280 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 tcpv4_add_listener(l);
283 }
Emeric Bruned760922010-10-22 17:59:25 +0200284 else if (ss.ss_family == AF_INET6) {
285 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
286 tcpv6_add_listener(l);
287 }
288 else {
Emeric Bruned760922010-10-22 17:59:25 +0200289 uxst_add_listener(l);
290 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200292 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 } /* end for(port) */
295 } /* end while(next) */
296 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200297 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 fail:
299 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200300 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301}
302
Willy Tarreau977b8e42006-12-29 14:19:17 +0100303/*
304 * Sends a warning if proxy <proxy> does not have at least one of the
305 * capabilities in <cap>. An optionnal <hint> may be added at the end
306 * of the warning to help the user. Returns 1 if a warning was emitted
307 * or 0 if the condition is valid.
308 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100309int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100310{
311 char *msg;
312
313 switch (cap) {
314 case PR_CAP_BE: msg = "no backend"; break;
315 case PR_CAP_FE: msg = "no frontend"; break;
316 case PR_CAP_RS: msg = "no ruleset"; break;
317 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
318 default: msg = "not enough"; break;
319 }
320
321 if (!(proxy->cap & cap)) {
322 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100323 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100324 return 1;
325 }
326 return 0;
327}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328
Willy Tarreau61d18892009-03-31 10:49:21 +0200329/* Report a warning if a rule is placed after a 'block' rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
334 if (!LIST_ISEMPTY(&proxy->block_cond)) {
335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a reqrewrite rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (proxy->req_exp) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a reqadd rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100360 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* Report a warning if a rule is placed after a redirect rule.
369 * Return 1 if the warning has been emitted, otherwise 0.
370 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100371int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200372{
373 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
374 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
375 file, line, arg);
376 return 1;
377 }
378 return 0;
379}
380
381/* Report a warning if a rule is placed after a 'use_backend' rule.
382 * Return 1 if the warning has been emitted, otherwise 0.
383 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
387 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
388 file, line, arg);
389 return 1;
390 }
391 return 0;
392}
393
394/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
398 warnif_rule_after_reqadd(proxy, file, line, arg) ||
399 warnif_rule_after_redirect(proxy, file, line, arg) ||
400 warnif_rule_after_use_backend(proxy, file, line, arg);
401}
402
403/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100404int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200405{
406 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
408 warnif_rule_after_use_backend(proxy, file, line, arg);
409}
410
411/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_redirect(proxy, file, line, arg) ||
415 warnif_rule_after_use_backend(proxy, file, line, arg);
416}
417
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418/* Report it if a request ACL condition uses some response-only parameters. It
419 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
420 * Note that <cond> may be NULL and then will be ignored.
421 */
422static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
423{
424 struct acl *acl;
425
426 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
427 return 0;
428
429 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
430 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
431 file, line, acl ? acl->name : "(unknown)");
432 return ERR_WARN;
433}
434
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100435/* Report it if a request ACL condition uses some request-only volatile parameters.
436 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
447 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 * parse a line in a <global> section. Returns the error code, 0 if OK, or
455 * any combination of :
456 * - ERR_ABORT: must abort ASAP
457 * - ERR_FATAL: we can continue parsing but not start the service
458 * - ERR_WARN: a warning has been emitted
459 * - ERR_ALERT: an alert has been emitted
460 * Only the two first ones can stop processing, the two others are just
461 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200463int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464{
Willy Tarreau058e9072009-07-20 09:30:05 +0200465 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200466 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467
468 if (!strcmp(args[0], "global")) { /* new section */
469 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200472 else if (!strcmp(args[0], "ca-base")) {
473#ifdef USE_OPENSSL
474 if (global.ca_base != NULL) {
475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
476 err_code |= ERR_ALERT;
477 goto out;
478 }
479 if (*(args[1]) == 0) {
480 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT | ERR_FATAL;
482 goto out;
483 }
484 global.ca_base = strdup(args[1]);
485#else
486 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
487 err_code |= ERR_ALERT | ERR_FATAL;
488 goto out;
489#endif
490 }
491 else if (!strcmp(args[0], "crt-base")) {
492#ifdef USE_OPENSSL
493 if (global.crt_base != NULL) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
495 err_code |= ERR_ALERT;
496 goto out;
497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
502 }
503 global.crt_base = strdup(args[1]);
504#else
505 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
506 err_code |= ERR_ALERT | ERR_FATAL;
507 goto out;
508#endif
509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510 else if (!strcmp(args[0], "daemon")) {
511 global.mode |= MODE_DAEMON;
512 }
513 else if (!strcmp(args[0], "debug")) {
514 global.mode |= MODE_DEBUG;
515 }
516 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100517 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200519 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100520 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200522 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100523 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100525 else if (!strcmp(args[0], "nosplice")) {
526 global.tune.options &= ~GTUNE_USE_SPLICE;
527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 else if (!strcmp(args[0], "quiet")) {
529 global.mode |= MODE_QUIET;
530 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200531 else if (!strcmp(args[0], "tune.maxpollevents")) {
532 if (global.tune.maxpollevents != 0) {
533 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 err_code |= ERR_ALERT;
535 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200541 }
542 global.tune.maxpollevents = atol(args[1]);
543 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100544 else if (!strcmp(args[0], "tune.maxaccept")) {
545 if (global.tune.maxaccept != 0) {
546 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 err_code |= ERR_ALERT;
548 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100554 }
555 global.tune.maxaccept = atol(args[1]);
556 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200557 else if (!strcmp(args[0], "tune.chksize")) {
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563 global.tune.chksize = atol(args[1]);
564 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200565#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100566 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.sslcachesize = atol(args[1]);
573 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100574 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
575 unsigned int ssllifetime;
576 const char *res;
577
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
582 }
583
584 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
585 if (res) {
586 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
587 file, linenum, *res, args[0]);
588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
590 }
591
592 global.tune.ssllifetime = ssllifetime;
593 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200594#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200595 else if (!strcmp(args[0], "tune.bufsize")) {
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
600 }
601 global.tune.bufsize = atol(args[1]);
602 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
603 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100604 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200605 }
606 else if (!strcmp(args[0], "tune.maxrewrite")) {
607 if (*(args[1]) == 0) {
608 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612 global.tune.maxrewrite = atol(args[1]);
613 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
614 global.tune.maxrewrite = global.tune.bufsize / 2;
615 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100616 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
617 if (global.tune.client_rcvbuf != 0) {
618 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
619 err_code |= ERR_ALERT;
620 goto out;
621 }
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.tune.client_rcvbuf = atol(args[1]);
628 }
629 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
630 if (global.tune.server_rcvbuf != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
632 err_code |= ERR_ALERT;
633 goto out;
634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
639 }
640 global.tune.server_rcvbuf = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "tune.sndbuf.client")) {
643 if (global.tune.client_sndbuf != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT;
646 goto out;
647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
652 }
653 global.tune.client_sndbuf = atol(args[1]);
654 }
655 else if (!strcmp(args[0], "tune.sndbuf.server")) {
656 if (global.tune.server_sndbuf != 0) {
657 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
658 err_code |= ERR_ALERT;
659 goto out;
660 }
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666 global.tune.server_sndbuf = atol(args[1]);
667 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200668 else if (!strcmp(args[0], "tune.pipesize")) {
669 if (*(args[1]) == 0) {
670 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674 global.tune.pipesize = atol(args[1]);
675 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100676 else if (!strcmp(args[0], "tune.http.cookielen")) {
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.cookie_len = atol(args[1]) + 1;
683 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200684 else if (!strcmp(args[0], "tune.http.maxhdr")) {
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 global.tune.max_http_hdr = atol(args[1]);
691 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100692 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
693#ifdef USE_ZLIB
694 if (*args[1]) {
695 global.tune.zlibmemlevel = atoi(args[1]);
696 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
697 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
698 file, linenum, args[0]);
699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
701 }
702 } else {
703 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
704 file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708#else
709 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712#endif
713 }
714 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
715#ifdef USE_ZLIB
716 if (*args[1]) {
717 global.tune.zlibwindowsize = atoi(args[1]);
718 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
719 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
720 file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 } else {
725 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
726 file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730#else
731 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734#endif
735 }
William Lallemandf3747832012-11-09 12:33:10 +0100736 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
737 if (*args[1]) {
738 global.tune.comp_maxlevel = atoi(args[1]);
739 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
740 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
741 file, linenum, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745 } else {
746 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
747 file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 else if (!strcmp(args[0], "uid")) {
753 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200754 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 global.uid = atol(args[1]);
764 }
765 else if (!strcmp(args[0], "gid")) {
766 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200767 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_ALERT;
769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 }
771 if (*(args[1]) == 0) {
772 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 global.gid = atol(args[1]);
777 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200778 /* user/group name handling */
779 else if (!strcmp(args[0], "user")) {
780 struct passwd *ha_user;
781 if (global.uid != 0) {
782 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200783 err_code |= ERR_ALERT;
784 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 }
786 errno = 0;
787 ha_user = getpwnam(args[1]);
788 if (ha_user != NULL) {
789 global.uid = (int)ha_user->pw_uid;
790 }
791 else {
792 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 +0200793 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200794 }
795 }
796 else if (!strcmp(args[0], "group")) {
797 struct group *ha_group;
798 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200799 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT;
801 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200802 }
803 errno = 0;
804 ha_group = getgrnam(args[1]);
805 if (ha_group != NULL) {
806 global.gid = (int)ha_group->gr_gid;
807 }
808 else {
809 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 +0200810 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200811 }
812 }
813 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 }
820 global.nbproc = atol(args[1]);
821 }
822 else if (!strcmp(args[0], "maxconn")) {
823 if (global.maxconn != 0) {
824 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_ALERT;
826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 global.maxconn = atol(args[1]);
834#ifdef SYSTEM_MAXCONN
835 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
836 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);
837 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840#endif /* SYSTEM_MAXCONN */
841 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200842 else if (!strcmp(args[0], "maxsslconn")) {
843#ifdef USE_OPENSSL
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.maxsslconn = atol(args[1]);
850#else
Emeric Brun0914df82012-10-02 18:45:42 +0200851 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200854#endif
855 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200856 else if (!strcmp(args[0], "maxconnrate")) {
857 if (global.cps_lim != 0) {
858 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT;
860 goto out;
861 }
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867 global.cps_lim = atol(args[1]);
868 }
William Lallemandd85f9172012-11-09 17:05:39 +0100869 else if (!strcmp(args[0], "maxcomprate")) {
870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 global.comp_rate_lim = atoi(args[1]) * 1024;
876 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100877 else if (!strcmp(args[0], "maxpipes")) {
878 if (global.maxpipes != 0) {
879 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200880 err_code |= ERR_ALERT;
881 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100882 }
883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100887 }
888 global.maxpipes = atol(args[1]);
889 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100890 else if (!strcmp(args[0], "maxzlibmem")) {
891 if (*(args[1]) == 0) {
892 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
William Lallemande3a7d992012-11-20 11:25:20 +0100896 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100898 else if (!strcmp(args[0], "maxcompcpuusage")) {
899 if (*(args[1]) == 0) {
900 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100905 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100906 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910}
911
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912 else if (!strcmp(args[0], "ulimit-n")) {
913 if (global.rlimit_nofile != 0) {
914 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 err_code |= ERR_ALERT;
916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 }
918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 }
923 global.rlimit_nofile = atol(args[1]);
924 }
925 else if (!strcmp(args[0], "chroot")) {
926 if (global.chroot != NULL) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200928 err_code |= ERR_ALERT;
929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 global.chroot = strdup(args[1]);
937 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200938 else if (!strcmp(args[0], "description")) {
939 int i, len=0;
940 char *d;
941
942 if (!*args[1]) {
943 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
944 file, linenum, args[0]);
945 err_code |= ERR_ALERT | ERR_FATAL;
946 goto out;
947 }
948
949 for(i=1; *args[i]; i++)
950 len += strlen(args[i])+1;
951
952 if (global.desc)
953 free(global.desc);
954
955 global.desc = d = (char *)calloc(1, len);
956
957 d += sprintf(d, "%s", args[1]);
958 for(i=2; *args[i]; i++)
959 d += sprintf(d, " %s", args[i]);
960 }
961 else if (!strcmp(args[0], "node")) {
962 int i;
963 char c;
964
965 for (i=0; args[1][i]; i++) {
966 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100967 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
968 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200969 break;
970 }
971
972 if (!i || args[1][i]) {
973 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
974 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
975 file, linenum, args[0]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979
980 if (global.node)
981 free(global.node);
982
983 global.node = strdup(args[1]);
984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 else if (!strcmp(args[0], "pidfile")) {
986 if (global.pidfile != NULL) {
987 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200988 err_code |= ERR_ALERT;
989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 }
991 if (*(args[1]) == 0) {
992 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200993 err_code |= ERR_ALERT | ERR_FATAL;
994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 }
996 global.pidfile = strdup(args[1]);
997 }
Emeric Bruned760922010-10-22 17:59:25 +0200998 else if (!strcmp(args[0], "unix-bind")) {
999 int cur_arg = 1;
1000 while (*(args[cur_arg])) {
1001 if (!strcmp(args[cur_arg], "prefix")) {
1002 if (global.unix_bind.prefix != NULL) {
1003 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1004 err_code |= ERR_ALERT;
1005 cur_arg += 2;
1006 continue;
1007 }
1008
1009 if (*(args[cur_arg+1]) == 0) {
1010 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1015 cur_arg += 2;
1016 continue;
1017 }
1018
1019 if (!strcmp(args[cur_arg], "mode")) {
1020
1021 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "uid")) {
1027
1028 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "gid")) {
1034
1035 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "user")) {
1041 struct passwd *user;
1042
1043 user = getpwnam(args[cur_arg + 1]);
1044 if (!user) {
1045 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1046 file, linenum, args[0], args[cur_arg + 1 ]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050
1051 global.unix_bind.ux.uid = user->pw_uid;
1052 cur_arg += 2;
1053 continue;
1054 }
1055
1056 if (!strcmp(args[cur_arg], "group")) {
1057 struct group *group;
1058
1059 group = getgrnam(args[cur_arg + 1]);
1060 if (!group) {
1061 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1062 file, linenum, args[0], args[cur_arg + 1 ]);
1063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
1065 }
1066
1067 global.unix_bind.ux.gid = group->gr_gid;
1068 cur_arg += 2;
1069 continue;
1070 }
1071
Willy Tarreaub48f9582011-09-05 01:17:06 +02001072 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001073 file, linenum, args[0]);
1074 err_code |= ERR_ALERT | ERR_FATAL;
1075 goto out;
1076 }
1077 }
William Lallemand0f99e342011-10-12 17:50:54 +02001078 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1079 /* delete previous herited or defined syslog servers */
1080 struct logsrv *back;
1081 struct logsrv *tmp;
1082
1083 if (*(args[1]) != 0) {
1084 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto out;
1087 }
1088
1089 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1090 LIST_DEL(&tmp->list);
1091 free(tmp);
1092 }
1093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001095 struct logsrv *logsrv;
1096
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 if (*(args[1]) == 0 || *(args[2]) == 0) {
1098 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001099 err_code |= ERR_ALERT | ERR_FATAL;
1100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 }
William Lallemand0f99e342011-10-12 17:50:54 +02001102
1103 logsrv = calloc(1, sizeof(struct logsrv));
1104
1105 logsrv->facility = get_log_facility(args[2]);
1106 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001109 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
1111
William Lallemand0f99e342011-10-12 17:50:54 +02001112 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001114 logsrv->level = get_log_level(args[3]);
1115 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120 }
1121
William Lallemand0f99e342011-10-12 17:50:54 +02001122 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001123 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001124 logsrv->minlvl = get_log_level(args[4]);
1125 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001126 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001128 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001129 }
1130 }
1131
Robert Tsai81ae1952007-12-05 10:47:29 +01001132 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001133 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001134 if (!sk) {
1135 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001136 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001137 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001138 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001139 goto out;
1140 }
William Lallemand0f99e342011-10-12 17:50:54 +02001141 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001142 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001143 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001144 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001145 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1146 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001147 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001148 goto out;
1149 }
William Lallemand0f99e342011-10-12 17:50:54 +02001150 logsrv->addr = *sk;
1151 if (!get_host_port(&logsrv->addr))
1152 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154
William Lallemand0f99e342011-10-12 17:50:54 +02001155 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001156 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001157 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1158 char *name;
1159 int len;
1160
1161 if (global.log_send_hostname != NULL) {
1162 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1163 err_code |= ERR_ALERT;
1164 goto out;
1165 }
1166
1167 if (*(args[1]))
1168 name = args[1];
1169 else
1170 name = hostname;
1171
1172 len = strlen(name);
1173
1174 /* We'll add a space after the name to respect the log format */
1175 free(global.log_send_hostname);
1176 global.log_send_hostname = malloc(len + 2);
1177 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1178 }
Kevinm48936af2010-12-22 16:08:21 +00001179 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1180 if (*(args[1]) == 0) {
1181 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185 free(global.log_tag);
1186 global.log_tag = strdup(args[1]);
1187 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001188 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1189 if (global.spread_checks != 0) {
1190 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT;
1192 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001193 }
1194 if (*(args[1]) == 0) {
1195 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001198 }
1199 global.spread_checks = atol(args[1]);
1200 if (global.spread_checks < 0 || global.spread_checks > 50) {
1201 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001202 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001203 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001205 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1206#ifdef USE_CPU_AFFINITY
1207 int cur_arg, i;
1208 unsigned int proc = 0;
1209 unsigned long cpus = 0;
1210
1211 if (strcmp(args[1], "all") == 0)
1212 proc = 0xFFFFFFFF;
1213 else if (strcmp(args[1], "odd") == 0)
1214 proc = 0x55555555;
1215 else if (strcmp(args[1], "even") == 0)
1216 proc = 0xAAAAAAAA;
1217 else {
1218 proc = atoi(args[1]);
1219 if (proc >= 1 && proc <= 32)
1220 proc = 1 << (proc - 1);
1221 }
1222
1223 if (!proc || !*args[2]) {
1224 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1225 file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229
1230 cur_arg = 2;
1231 while (*args[cur_arg]) {
1232 unsigned int low, high;
1233
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001234 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001235 char *dash = strchr(args[cur_arg], '-');
1236
1237 low = high = str2uic(args[cur_arg]);
1238 if (dash)
1239 high = str2uic(dash + 1);
1240
1241 if (high < low) {
1242 unsigned int swap = low;
1243 low = high;
1244 high = swap;
1245 }
1246
1247 if (low < 0 || high >= sizeof(long) * 8) {
1248 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1249 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253
1254 while (low <= high)
1255 cpus |= 1UL << low++;
1256 }
1257 else {
1258 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1259 file, linenum, args[0], args[cur_arg]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 cur_arg++;
1264 }
1265 for (i = 0; i < 32; i++)
1266 if (proc & (1 << i))
1267 global.cpu_map[i] = cpus;
1268#else
1269 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
1272#endif
1273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001275 struct cfg_kw_list *kwl;
1276 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001277 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001278
1279 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1280 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1281 if (kwl->kw[index].section != CFG_GLOBAL)
1282 continue;
1283 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001284 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001285 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001286 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001287 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001288 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001289 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001290 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001291 err_code |= ERR_WARN;
1292 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001293 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001294 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001295 }
1296 }
1297 }
1298
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001302
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001304 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001305 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001306}
1307
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001308void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001310 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 defproxy.mode = PR_MODE_TCP;
1312 defproxy.state = PR_STNEW;
1313 defproxy.maxconn = cfg_maxpconn;
1314 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001315
1316 defproxy.defsrv.inter = DEF_CHKINTR;
1317 defproxy.defsrv.fastinter = 0;
1318 defproxy.defsrv.downinter = 0;
1319 defproxy.defsrv.rise = DEF_RISETIME;
1320 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001321 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001322 defproxy.defsrv.maxqueue = 0;
1323 defproxy.defsrv.minconn = 0;
1324 defproxy.defsrv.maxconn = 0;
1325 defproxy.defsrv.slowstart = 0;
1326 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1327 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1328 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329}
1330
Willy Tarreauade5ec42010-01-28 19:33:49 +01001331
1332static int create_cond_regex_rule(const char *file, int line,
1333 struct proxy *px, int dir, int action, int flags,
1334 const char *cmd, const char *reg, const char *repl,
1335 const char **cond_start)
1336{
1337 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001338 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001339 const char *err;
1340 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001341 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001342
1343 if (px == &defproxy) {
1344 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto err;
1347 }
1348
1349 if (*reg == 0) {
1350 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto err;
1353 }
1354
1355 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1356 err_code |= ERR_WARN;
1357
Willy Tarreau5321c422010-01-28 20:35:13 +01001358 if (cond_start &&
1359 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001360 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1361 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1362 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto err;
1365 }
1366 }
1367 else if (cond_start && **cond_start) {
1368 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1369 file, line, cmd, *cond_start);
1370 err_code |= ERR_ALERT | ERR_FATAL;
1371 goto err;
1372 }
1373
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001374 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001375 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001376 else
1377 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001378
Willy Tarreauade5ec42010-01-28 19:33:49 +01001379 preg = calloc(1, sizeof(regex_t));
1380 if (!preg) {
1381 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1382 err_code = ERR_ALERT | ERR_FATAL;
1383 goto err;
1384 }
1385
1386 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1387 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1388 err_code = ERR_ALERT | ERR_FATAL;
1389 goto err;
1390 }
1391
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001392 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001393 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001394 if (repl && err) {
1395 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1396 file, line, cmd, *err);
1397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto err;
1399 }
1400
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001401 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001402 err_code |= ERR_WARN;
1403
Willy Tarreauf4068b62012-05-08 17:37:49 +02001404 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001405 return err_code;
1406 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001407 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001408 free(preg);
1409 return err_code;
1410}
1411
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001413 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001414 * Returns the error code, 0 if OK, or any combination of :
1415 * - ERR_ABORT: must abort ASAP
1416 * - ERR_FATAL: we can continue parsing but not start the service
1417 * - ERR_WARN: a warning has been emitted
1418 * - ERR_ALERT: an alert has been emitted
1419 * Only the two first ones can stop processing, the two others are just
1420 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001422int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1423{
1424 static struct peers *curpeers = NULL;
1425 struct peer *newpeer = NULL;
1426 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001427 struct bind_conf *bind_conf;
1428 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001429 int err_code = 0;
1430
1431 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1432
1433 err = invalid_char(args[1]);
1434 if (err) {
1435 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1436 file, linenum, *err, args[0], args[1]);
1437 err_code |= ERR_ALERT | ERR_FATAL;
1438 }
1439
1440 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1441 /*
1442 * If there are two proxies with the same name only following
1443 * combinations are allowed:
1444 */
1445 if (strcmp(curpeers->id, args[1]) == 0) {
1446 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1447 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1448 err_code |= ERR_WARN;
1449 }
1450 }
1451
1452 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1453 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1454 err_code |= ERR_ALERT | ERR_ABORT;
1455 goto out;
1456 }
1457
1458 curpeers->next = peers;
1459 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001460 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001461 curpeers->conf.line = linenum;
1462 curpeers->last_change = now.tv_sec;
1463 curpeers->id = strdup(args[1]);
1464 }
1465 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1466 char *rport, *raddr;
1467 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001468 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001469 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001470
1471 if (!*args[2]) {
1472 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1473 file, linenum, args[0]);
1474 err_code |= ERR_ALERT | ERR_FATAL;
1475 goto out;
1476 }
1477
1478 err = invalid_char(args[1]);
1479 if (err) {
1480 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1481 file, linenum, *err, args[1]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1487 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1488 err_code |= ERR_ALERT | ERR_ABORT;
1489 goto out;
1490 }
1491
1492 /* the peers are linked backwards first */
1493 curpeers->count++;
1494 newpeer->next = curpeers->remote;
1495 curpeers->remote = newpeer;
1496 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001497 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001498 newpeer->conf.line = linenum;
1499
1500 newpeer->last_change = now.tv_sec;
1501 newpeer->id = strdup(args[1]);
1502
1503 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001504 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001505 if (rport) {
1506 *rport++ = 0;
1507 realport = atol(rport);
1508 }
1509 if (!realport) {
1510 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau846257e2013-01-24 00:29:37 +01001512 free(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001513 goto out;
1514 }
1515
Willy Tarreaufab5a432011-03-04 15:31:53 +01001516 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001517 free(raddr);
1518 if (!sk) {
1519 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1520 err_code |= ERR_ALERT | ERR_FATAL;
1521 goto out;
1522 }
1523 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001524 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001525 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001526 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001527
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001528 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001529 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1530 file, linenum, newpeer->addr.ss_family, args[2]);
1531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
1533 }
1534
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001535 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001536
1537 if (strcmp(newpeer->id, localpeer) == 0) {
1538 /* Current is local peer, it define a frontend */
1539 newpeer->local = 1;
1540
1541 if (!curpeers->peers_fe) {
1542 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1543 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1544 err_code |= ERR_ALERT | ERR_ABORT;
1545 goto out;
1546 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001547
Willy Tarreau237250c2011-07-29 01:49:03 +02001548 init_new_proxy(curpeers->peers_fe);
1549 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001550
1551 curpeers->peers_fe->last_change = now.tv_sec;
1552 curpeers->peers_fe->id = strdup(args[1]);
1553 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001554 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001555 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1556 curpeers->peers_fe->timeout.connect = 5000;
1557 curpeers->peers_fe->accept = peer_accept;
1558 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001559 curpeers->peers_fe->conf.file = strdup(file);
1560 curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001561
1562 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1563
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001564 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1565 if (err_msg && *err_msg) {
1566 indent_msg(&err_msg, 2);
1567 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1568 }
1569 else
1570 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1571 file, linenum, args[0], args[1], args[2]);
1572 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001573 err_code |= ERR_FATAL;
1574 goto out;
1575 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001576
1577 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1578 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1579 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1580 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1581 l->accept = session_accept;
1582 l->handler = process_session;
1583 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1584 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1585 global.maxsock += l->maxconn;
1586 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001587 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001588 else {
1589 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1590 file, linenum, args[0], args[1],
1591 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1592 err_code |= ERR_FATAL;
1593 goto out;
1594 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001595 }
1596 } /* neither "peer" nor "peers" */
1597 else if (*args[0] != 0) {
1598 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1599 err_code |= ERR_ALERT | ERR_FATAL;
1600 goto out;
1601 }
1602
1603out:
1604 return err_code;
1605}
1606
1607
Willy Tarreau3842f002009-06-14 11:39:52 +02001608int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609{
1610 static struct proxy *curproxy = NULL;
1611 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001612 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001613 int rc;
1614 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001615 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001616 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001617 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001618 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001619 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620
Willy Tarreau977b8e42006-12-29 14:19:17 +01001621 if (!strcmp(args[0], "listen"))
1622 rc = PR_CAP_LISTEN;
1623 else if (!strcmp(args[0], "frontend"))
1624 rc = PR_CAP_FE | PR_CAP_RS;
1625 else if (!strcmp(args[0], "backend"))
1626 rc = PR_CAP_BE | PR_CAP_RS;
1627 else if (!strcmp(args[0], "ruleset"))
1628 rc = PR_CAP_RS;
1629 else
1630 rc = PR_CAP_NONE;
1631
1632 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 if (!*args[1]) {
1634 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1635 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_ABORT;
1638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001640
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001641 err = invalid_char(args[1]);
1642 if (err) {
1643 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1644 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001646 }
1647
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001648 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1649 /*
1650 * If there are two proxies with the same name only following
1651 * combinations are allowed:
1652 *
1653 * listen backend frontend ruleset
1654 * listen - - - -
1655 * backend - - OK -
1656 * frontend - OK - -
1657 * ruleset - - - -
1658 */
1659
1660 if (!strcmp(curproxy->id, args[1]) &&
1661 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1662 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001663 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1664 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1665 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001666 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001667 }
1668 }
1669
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1671 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001672 err_code |= ERR_ALERT | ERR_ABORT;
1673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001675
Willy Tarreau97cb7802010-01-03 20:23:58 +01001676 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001677 curproxy->next = proxy;
1678 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001679 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001680 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001681 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001682 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001683 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684
1685 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001686 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001687 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001688 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001689
Willy Tarreau4348fad2012-09-20 16:48:07 +02001690 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1691
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001692 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1693 if (err_msg && *err_msg) {
1694 indent_msg(&err_msg, 2);
1695 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1696 }
1697 else
1698 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1699 file, linenum, args[0], args[1], args[2]);
1700 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001701 err_code |= ERR_FATAL;
1702 goto out;
1703 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001704
Willy Tarreau4348fad2012-09-20 16:48:07 +02001705 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001706 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 }
1709
1710 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001711 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001712 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001713
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001716 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001717 curproxy->no_options = defproxy.no_options;
1718 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001719 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001720 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001721 curproxy->except_net = defproxy.except_net;
1722 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001723 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001724 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001726 if (defproxy.fwdfor_hdr_len) {
1727 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1728 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1729 }
1730
Willy Tarreaub86db342009-11-30 11:50:16 +01001731 if (defproxy.orgto_hdr_len) {
1732 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1733 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1734 }
1735
Mark Lamourinec2247f02012-01-04 13:02:01 -05001736 if (defproxy.server_id_hdr_len) {
1737 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1738 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1739 }
1740
Willy Tarreau977b8e42006-12-29 14:19:17 +01001741 if (curproxy->cap & PR_CAP_FE) {
1742 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001743 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001744 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001745
1746 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001747 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1748 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001749
1750 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752
Willy Tarreau977b8e42006-12-29 14:19:17 +01001753 if (curproxy->cap & PR_CAP_BE) {
1754 curproxy->fullconn = defproxy.fullconn;
1755 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001757 if (defproxy.check_req) {
1758 curproxy->check_req = calloc(1, defproxy.check_len);
1759 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1760 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001761 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001763 if (defproxy.expect_str) {
1764 curproxy->expect_str = strdup(defproxy.expect_str);
1765 if (defproxy.expect_regex) {
1766 /* note: this regex is known to be valid */
1767 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1768 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1769 }
1770 }
1771
Willy Tarreau67402132012-05-31 20:40:20 +02001772 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001773 if (defproxy.cookie_name)
1774 curproxy->cookie_name = strdup(defproxy.cookie_name);
1775 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001776 if (defproxy.cookie_domain)
1777 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001778
Willy Tarreau31936852010-10-06 16:59:56 +02001779 if (defproxy.cookie_maxidle)
1780 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1781
1782 if (defproxy.cookie_maxlife)
1783 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1784
Emeric Brun647caf12009-06-30 17:57:00 +02001785 if (defproxy.rdp_cookie_name)
1786 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1787 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1788
Willy Tarreau01732802007-11-01 22:48:15 +01001789 if (defproxy.url_param_name)
1790 curproxy->url_param_name = strdup(defproxy.url_param_name);
1791 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001792
Benoitaffb4812009-03-25 13:02:10 +01001793 if (defproxy.hh_name)
1794 curproxy->hh_name = strdup(defproxy.hh_name);
1795 curproxy->hh_len = defproxy.hh_len;
1796 curproxy->hh_match_domain = defproxy.hh_match_domain;
1797
Willy Tarreauef9a3602012-12-08 22:29:20 +01001798 if (defproxy.conn_src.iface_name)
1799 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1800 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1801 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001804 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001805 if (defproxy.capture_name)
1806 curproxy->capture_name = strdup(defproxy.capture_name);
1807 curproxy->capture_namelen = defproxy.capture_namelen;
1808 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810
Willy Tarreau977b8e42006-12-29 14:19:17 +01001811 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001812 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001813 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001814 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001815 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001816 curproxy->uri_auth = defproxy.uri_auth;
1817 curproxy->mon_net = defproxy.mon_net;
1818 curproxy->mon_mask = defproxy.mon_mask;
1819 if (defproxy.monitor_uri)
1820 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1821 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001822 if (defproxy.defbe.name)
1823 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001824
1825 /* get either a pointer to the logformat string or a copy of it */
1826 curproxy->logformat_string = defproxy.logformat_string;
1827 if (curproxy->logformat_string &&
1828 curproxy->logformat_string != default_http_log_format &&
1829 curproxy->logformat_string != default_tcp_log_format &&
1830 curproxy->logformat_string != clf_http_log_format)
1831 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001832 }
1833
1834 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001835 curproxy->timeout.connect = defproxy.timeout.connect;
1836 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001837 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001838 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001839 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001840 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001841 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001842 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001843 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001844 }
1845
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001847
1848 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001849 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001850 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001851 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001852 LIST_INIT(&node->list);
1853 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1854 }
1855
Willy Tarreau196729e2012-05-31 19:30:26 +02001856 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1857 if (curproxy->uniqueid_format_string)
1858 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001859
1860 /* copy default header unique id */
1861 if (defproxy.header_unique_id)
1862 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1863
William Lallemand82fe75c2012-10-23 10:25:10 +02001864 /* default compression options */
1865 if (defproxy.comp != NULL) {
1866 curproxy->comp = calloc(1, sizeof(struct comp));
1867 curproxy->comp->algos = defproxy.comp->algos;
1868 curproxy->comp->types = defproxy.comp->types;
1869 }
1870
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001872 curproxy->conf.used_listener_id = EB_ROOT;
1873 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001874
Willy Tarreau93893792009-07-23 13:19:11 +02001875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001876 }
1877 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1878 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001879 /* FIXME-20070101: we should do this too at the end of the
1880 * config parsing to free all default values.
1881 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001882 free(defproxy.check_req);
1883 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001884 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001885 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001886 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001887 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001888 free(defproxy.capture_name);
1889 free(defproxy.monitor_uri);
1890 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001891 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001892 free(defproxy.fwdfor_hdr_name);
1893 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001894 free(defproxy.orgto_hdr_name);
1895 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001896 free(defproxy.server_id_hdr_name);
1897 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001898 free(defproxy.expect_str);
1899 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001900
Willy Tarreau39b06652012-06-01 10:58:06 +02001901 if (defproxy.logformat_string != default_http_log_format &&
1902 defproxy.logformat_string != default_tcp_log_format &&
1903 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001904 free(defproxy.logformat_string);
1905
1906 free(defproxy.uniqueid_format_string);
1907
Willy Tarreaua534fea2008-08-03 12:19:50 +02001908 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001909 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001910
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 /* we cannot free uri_auth because it might already be used */
1912 init_default_instance();
1913 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001914 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 }
1917 else if (curproxy == NULL) {
1918 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001919 err_code |= ERR_ALERT | ERR_FATAL;
1920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 }
1922
Willy Tarreau977b8e42006-12-29 14:19:17 +01001923
1924 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001926 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001927 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001928 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001929
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 if (curproxy == &defproxy) {
1931 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001935 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001936 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937
Emeric Bruned760922010-10-22 17:59:25 +02001938 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001939 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001944
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001945 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001946
1947 /* use default settings for unix sockets */
1948 bind_conf->ux.uid = global.unix_bind.ux.uid;
1949 bind_conf->ux.gid = global.unix_bind.ux.gid;
1950 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001951
1952 /* NOTE: the following line might create several listeners if there
1953 * are comma-separated IPs or port ranges. So all further processing
1954 * will have to be applied to all listeners created after last_listen.
1955 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001956 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1957 if (err_msg && *err_msg) {
1958 indent_msg(&err_msg, 2);
1959 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1960 }
1961 else
1962 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1963 file, linenum, args[0], args[1]);
1964 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_ALERT | ERR_FATAL;
1966 goto out;
1967 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001968
Willy Tarreau4348fad2012-09-20 16:48:07 +02001969 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1970 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001971 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001972 }
1973
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001974 cur_arg = 2;
1975 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001976 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001977 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001978 char *err;
1979
Willy Tarreau26982662012-09-12 23:17:10 +02001980 kw = bind_find_kw(args[cur_arg]);
1981 if (kw) {
1982 char *err = NULL;
1983 int code;
1984
1985 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001986 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1987 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001988 cur_arg += 1 + kw->skip ;
1989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
1991 }
1992
Willy Tarreau4348fad2012-09-20 16:48:07 +02001993 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001994 err_code |= code;
1995
1996 if (code) {
1997 if (err && *err) {
1998 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001999 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002000 }
2001 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002002 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2003 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002004 if (code & ERR_FATAL) {
2005 free(err);
2006 cur_arg += 1 + kw->skip;
2007 goto out;
2008 }
2009 }
2010 free(err);
2011 cur_arg += 1 + kw->skip;
2012 continue;
2013 }
2014
Willy Tarreau8638f482012-09-18 18:01:17 +02002015 err = NULL;
2016 if (!bind_dumped) {
2017 bind_dump_kws(&err);
2018 indent_msg(&err, 4);
2019 bind_dumped = 1;
2020 }
2021
2022 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2023 file, linenum, args[0], args[1], args[cur_arg],
2024 err ? " Registered keywords :" : "", err ? err : "");
2025 free(err);
2026
Willy Tarreau93893792009-07-23 13:19:11 +02002027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002029 }
Willy Tarreau93893792009-07-23 13:19:11 +02002030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 }
2032 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2033 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2034 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2035 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002036 err_code |= ERR_ALERT | ERR_FATAL;
2037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002039 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002040 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002041
Willy Tarreaubaaee002006-06-26 02:48:02 +02002042 /* flush useless bits */
2043 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002045 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002046 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002047 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002048 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002049
Willy Tarreau1c47f852006-07-09 08:22:27 +02002050 if (!*args[1]) {
2051 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002055 }
2056
Willy Tarreaua534fea2008-08-03 12:19:50 +02002057 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002058 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002059 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002060 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002061 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2062
Willy Tarreau93893792009-07-23 13:19:11 +02002063 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2066 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2067 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2068 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2069 else {
2070 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073 }
2074 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002075 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002076 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002077
2078 if (curproxy == &defproxy) {
2079 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2080 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002081 err_code |= ERR_ALERT | ERR_FATAL;
2082 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002083 }
2084
2085 if (!*args[1]) {
2086 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2087 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002088 err_code |= ERR_ALERT | ERR_FATAL;
2089 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002090 }
2091
2092 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002093 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002094
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002095 if (curproxy->uuid <= 0) {
2096 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002097 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002100 }
2101
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002102 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2103 if (node) {
2104 struct proxy *target = container_of(node, struct proxy, conf.id);
2105 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2106 file, linenum, proxy_type_str(curproxy), curproxy->id,
2107 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2108 err_code |= ERR_ALERT | ERR_FATAL;
2109 goto out;
2110 }
2111 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002112 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002113 else if (!strcmp(args[0], "description")) {
2114 int i, len=0;
2115 char *d;
2116
Cyril Bonté99ed3272010-01-24 23:29:44 +01002117 if (curproxy == &defproxy) {
2118 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2119 file, linenum, args[0]);
2120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
2122 }
2123
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002124 if (!*args[1]) {
2125 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2126 file, linenum, args[0]);
2127 return -1;
2128 }
2129
2130 for(i=1; *args[i]; i++)
2131 len += strlen(args[i])+1;
2132
2133 d = (char *)calloc(1, len);
2134 curproxy->desc = d;
2135
2136 d += sprintf(d, "%s", args[1]);
2137 for(i=2; *args[i]; i++)
2138 d += sprintf(d, " %s", args[i]);
2139
2140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2142 curproxy->state = PR_STSTOPPED;
2143 }
2144 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2145 curproxy->state = PR_STNEW;
2146 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002147 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2148 int cur_arg = 1;
2149 unsigned int set = 0;
2150
2151 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002152 unsigned int low, high;
2153
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002154 if (strcmp(args[cur_arg], "all") == 0) {
2155 set = 0;
2156 break;
2157 }
2158 else if (strcmp(args[cur_arg], "odd") == 0) {
2159 set |= 0x55555555;
2160 }
2161 else if (strcmp(args[cur_arg], "even") == 0) {
2162 set |= 0xAAAAAAAA;
2163 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002164 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002165 char *dash = strchr(args[cur_arg], '-');
2166
2167 low = high = str2uic(args[cur_arg]);
2168 if (dash)
2169 high = str2uic(dash + 1);
2170
2171 if (high < low) {
2172 unsigned int swap = low;
2173 low = high;
2174 high = swap;
2175 }
2176
2177 if (low < 1 || high > 32) {
2178 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002179 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002182 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002183
2184 if (high > global.nbproc) {
2185 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2186 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002187 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002188 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002189 while (low <= high)
2190 set |= 1 << (low++ - 1);
2191 }
2192 else {
2193 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2194 file, linenum, args[0]);
2195 err_code |= ERR_ALERT | ERR_FATAL;
2196 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002197 }
2198 cur_arg++;
2199 }
2200 curproxy->bind_proc = set;
2201 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002202 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002203 if (curproxy == &defproxy) {
2204 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002207 }
2208
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002209 err = invalid_char(args[1]);
2210 if (err) {
2211 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2212 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002213 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002214 }
2215
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002216 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2217 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2218 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002221 }
2222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002223 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2224 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225
Willy Tarreau977b8e42006-12-29 14:19:17 +01002226 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002227 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002228
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 if (*(args[1]) == 0) {
2230 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2231 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002235
Willy Tarreau67402132012-05-31 20:40:20 +02002236 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002237 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002238 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002239 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 curproxy->cookie_name = strdup(args[1]);
2241 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002242
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 cur_arg = 2;
2244 while (*(args[cur_arg])) {
2245 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002246 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 }
2248 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002249 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 }
2251 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002252 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 }
2254 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002255 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 }
2257 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002258 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002260 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002261 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002264 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002266 else if (!strcmp(args[cur_arg], "httponly")) {
2267 curproxy->ck_opts |= PR_CK_HTTPONLY;
2268 }
2269 else if (!strcmp(args[cur_arg], "secure")) {
2270 curproxy->ck_opts |= PR_CK_SECURE;
2271 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002272 else if (!strcmp(args[cur_arg], "domain")) {
2273 if (!*args[cur_arg + 1]) {
2274 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2275 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002276 err_code |= ERR_ALERT | ERR_FATAL;
2277 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002278 }
2279
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002280 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002281 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002282 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2283 " dots nor does not start with a dot."
2284 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002285 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002286 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002287 }
2288
2289 err = invalid_domainchar(args[cur_arg + 1]);
2290 if (err) {
2291 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2292 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002295 }
2296
Willy Tarreau68a897b2009-12-03 23:28:34 +01002297 if (!curproxy->cookie_domain) {
2298 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2299 } else {
2300 /* one domain was already specified, add another one by
2301 * building the string which will be returned along with
2302 * the cookie.
2303 */
2304 char *new_ptr;
2305 int new_len = strlen(curproxy->cookie_domain) +
2306 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2307 new_ptr = malloc(new_len);
2308 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2309 free(curproxy->cookie_domain);
2310 curproxy->cookie_domain = new_ptr;
2311 }
Willy Tarreau31936852010-10-06 16:59:56 +02002312 cur_arg++;
2313 }
2314 else if (!strcmp(args[cur_arg], "maxidle")) {
2315 unsigned int maxidle;
2316 const char *res;
2317
2318 if (!*args[cur_arg + 1]) {
2319 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2320 file, linenum, args[cur_arg]);
2321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
2323 }
2324
2325 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2326 if (res) {
2327 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2328 file, linenum, *res, args[cur_arg]);
2329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
2331 }
2332 curproxy->cookie_maxidle = maxidle;
2333 cur_arg++;
2334 }
2335 else if (!strcmp(args[cur_arg], "maxlife")) {
2336 unsigned int maxlife;
2337 const char *res;
2338
2339 if (!*args[cur_arg + 1]) {
2340 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2341 file, linenum, args[cur_arg]);
2342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
2344 }
2345
2346 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2347 if (res) {
2348 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2349 file, linenum, *res, args[cur_arg]);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
2353 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002354 cur_arg++;
2355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002357 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 +02002358 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 }
2362 cur_arg++;
2363 }
Willy Tarreau67402132012-05-31 20:40:20 +02002364 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2366 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 }
2369
Willy Tarreau67402132012-05-31 20:40:20 +02002370 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2372 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002373 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002375
Willy Tarreau67402132012-05-31 20:40:20 +02002376 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002377 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2378 file, linenum);
2379 err_code |= ERR_ALERT | ERR_FATAL;
2380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002382 else if (!strcmp(args[0], "persist")) { /* persist */
2383 if (*(args[1]) == 0) {
2384 Alert("parsing [%s:%d] : missing persist method.\n",
2385 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002388 }
2389
2390 if (!strncmp(args[1], "rdp-cookie", 10)) {
2391 curproxy->options2 |= PR_O2_RDPC_PRST;
2392
Emeric Brunb982a3d2010-01-04 15:45:53 +01002393 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002394 const char *beg, *end;
2395
2396 beg = args[1] + 11;
2397 end = strchr(beg, ')');
2398
2399 if (!end || end == beg) {
2400 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2401 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002404 }
2405
2406 free(curproxy->rdp_cookie_name);
2407 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2408 curproxy->rdp_cookie_len = end-beg;
2409 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002410 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002411 free(curproxy->rdp_cookie_name);
2412 curproxy->rdp_cookie_name = strdup("msts");
2413 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2414 }
2415 else { /* syntax */
2416 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2417 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002420 }
2421 }
2422 else {
2423 Alert("parsing [%s:%d] : unknown persist method.\n",
2424 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002427 }
2428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002430 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002432 if (curproxy == &defproxy) {
2433 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
2436 }
2437
Willy Tarreau977b8e42006-12-29 14:19:17 +01002438 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002440
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002442 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 }
2447 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002448 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 curproxy->appsession_name = strdup(args[1]);
2450 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2451 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002452 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2453 if (err) {
2454 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2455 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002458 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002459 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002460
Willy Tarreau51041c72007-09-09 21:56:53 +02002461 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2462 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002463 err_code |= ERR_ALERT | ERR_ABORT;
2464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002466
2467 cur_arg = 6;
2468 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002469 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2470 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002471 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002472 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002473 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002474 } else if (!strcmp(args[cur_arg], "prefix")) {
2475 curproxy->options2 |= PR_O2_AS_PFX;
2476 } else if (!strcmp(args[cur_arg], "mode")) {
2477 if (!*args[cur_arg + 1]) {
2478 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2479 file, linenum, args[0], args[cur_arg]);
2480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
2482 }
2483
2484 cur_arg++;
2485 if (!strcmp(args[cur_arg], "query-string")) {
2486 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2487 curproxy->options2 |= PR_O2_AS_M_QS;
2488 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2489 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2490 curproxy->options2 |= PR_O2_AS_M_PP;
2491 } else {
2492 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002497 cur_arg++;
2498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 } /* Url App Session */
2500 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002501 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002502 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002503
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002505 if (curproxy == &defproxy) {
2506 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
2509 }
2510
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 if (*(args[4]) == 0) {
2512 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2513 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002517 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 curproxy->capture_name = strdup(args[2]);
2519 curproxy->capture_namelen = strlen(curproxy->capture_name);
2520 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 curproxy->to_log |= LW_COOKIE;
2522 }
2523 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2524 struct cap_hdr *hdr;
2525
2526 if (curproxy == &defproxy) {
2527 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 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530 }
2531
2532 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2533 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2534 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537 }
2538
2539 hdr = calloc(sizeof(struct cap_hdr), 1);
2540 hdr->next = curproxy->req_cap;
2541 hdr->name = strdup(args[3]);
2542 hdr->namelen = strlen(args[3]);
2543 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002544 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 hdr->index = curproxy->nb_req_cap++;
2546 curproxy->req_cap = hdr;
2547 curproxy->to_log |= LW_REQHDR;
2548 }
2549 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2550 struct cap_hdr *hdr;
2551
2552 if (curproxy == &defproxy) {
2553 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 +02002554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 }
2557
2558 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2559 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2560 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 }
2564 hdr = calloc(sizeof(struct cap_hdr), 1);
2565 hdr->next = curproxy->rsp_cap;
2566 hdr->name = strdup(args[3]);
2567 hdr->namelen = strlen(args[3]);
2568 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002569 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 hdr->index = curproxy->nb_rsp_cap++;
2571 curproxy->rsp_cap = hdr;
2572 curproxy->to_log |= LW_RSPHDR;
2573 }
2574 else {
2575 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2576 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
2580 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002582 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002584
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 if (*(args[1]) == 0) {
2586 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2587 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002588 err_code |= ERR_ALERT | ERR_FATAL;
2589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 }
2591 curproxy->conn_retries = atol(args[1]);
2592 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002593 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002594 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002595
2596 if (curproxy == &defproxy) {
2597 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
2600 }
2601
Willy Tarreau20b0de52012-12-24 15:45:22 +01002602 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2603 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2604 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2605 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2606 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2607 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002608 file, linenum, args[0]);
2609 err_code |= ERR_WARN;
2610 }
2611
Willy Tarreauff011f22011-01-06 17:51:27 +01002612 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002613
Willy Tarreauff011f22011-01-06 17:51:27 +01002614 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002615 err_code |= ERR_ALERT | ERR_ABORT;
2616 goto out;
2617 }
2618
Willy Tarreauff011f22011-01-06 17:51:27 +01002619 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2620 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002621 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002622 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2623 /* set the header name and length into the proxy structure */
2624 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2625 err_code |= ERR_WARN;
2626
2627 if (!*args[1]) {
2628 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2629 file, linenum, args[0]);
2630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
2633
2634 /* set the desired header name */
2635 free(curproxy->server_id_hdr_name);
2636 curproxy->server_id_hdr_name = strdup(args[1]);
2637 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2638 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002639 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002640 if (curproxy == &defproxy) {
2641 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002644 }
2645
Willy Tarreauef6494c2010-01-28 17:12:36 +01002646 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002647 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2648 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002651 }
2652
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002653 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2654 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2655 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002658 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002659
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002660 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002661 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002662 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002663 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002664 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002665
Cyril Bonté99ed3272010-01-24 23:29:44 +01002666 if (curproxy == &defproxy) {
2667 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
2670 }
2671
Willy Tarreau4baae242012-12-27 12:00:31 +01002672 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2673 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2674 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002677 }
2678
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002679 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002680 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2681 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002682 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002683 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002684 struct switching_rule *rule;
2685
Willy Tarreaub099aca2008-10-12 17:26:37 +02002686 if (curproxy == &defproxy) {
2687 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_ALERT | ERR_FATAL;
2689 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002690 }
2691
Willy Tarreau55ea7572007-06-17 19:56:27 +02002692 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002693 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002694
2695 if (*(args[1]) == 0) {
2696 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002699 }
2700
Willy Tarreauef6494c2010-01-28 17:12:36 +01002701 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002702 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2703 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002706 }
2707
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002708 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2709 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2710 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002713 }
2714
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002715 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002716
Willy Tarreau55ea7572007-06-17 19:56:27 +02002717 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2718 rule->cond = cond;
2719 rule->be.name = strdup(args[1]);
2720 LIST_INIT(&rule->list);
2721 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2722 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002723 else if (strcmp(args[0], "use-server") == 0) {
2724 struct server_rule *rule;
2725
2726 if (curproxy == &defproxy) {
2727 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
2730 }
2731
2732 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2733 err_code |= ERR_WARN;
2734
2735 if (*(args[1]) == 0) {
2736 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740
2741 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2742 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2743 file, linenum, args[0]);
2744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
2746 }
2747
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002748 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2749 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2750 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
2753 }
2754
2755 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2756
2757 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2758 rule->cond = cond;
2759 rule->srv.name = strdup(args[1]);
2760 LIST_INIT(&rule->list);
2761 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2762 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2763 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002764 else if ((!strcmp(args[0], "force-persist")) ||
2765 (!strcmp(args[0], "ignore-persist"))) {
2766 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002767
2768 if (curproxy == &defproxy) {
2769 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
2772 }
2773
2774 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2775 err_code |= ERR_WARN;
2776
Willy Tarreauef6494c2010-01-28 17:12:36 +01002777 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002778 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2779 file, linenum, args[0]);
2780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
2782 }
2783
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002784 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2785 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2786 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002787 err_code |= ERR_ALERT | ERR_FATAL;
2788 goto out;
2789 }
2790
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002791 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002792
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002793 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002794 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002795 if (!strcmp(args[0], "force-persist")) {
2796 rule->type = PERSIST_TYPE_FORCE;
2797 } else {
2798 rule->type = PERSIST_TYPE_IGNORE;
2799 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002800 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002801 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002802 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002803 else if (!strcmp(args[0], "stick-table")) {
2804 int myidx = 1;
2805
Emeric Brun32da3c42010-09-23 18:39:19 +02002806 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002807 curproxy->table.type = (unsigned int)-1;
2808 while (*args[myidx]) {
2809 const char *err;
2810
2811 if (strcmp(args[myidx], "size") == 0) {
2812 myidx++;
2813 if (!*(args[myidx])) {
2814 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2815 file, linenum, args[myidx-1]);
2816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
2818 }
2819 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2820 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2821 file, linenum, *err, args[myidx-1]);
2822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
2824 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002825 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002826 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002827 else if (strcmp(args[myidx], "peers") == 0) {
2828 myidx++;
2829 if (!*(args[myidx])) {
2830 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2831 file, linenum, args[myidx-1]);
2832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
2834 }
2835 curproxy->table.peers.name = strdup(args[myidx++]);
2836 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002837 else if (strcmp(args[myidx], "expire") == 0) {
2838 myidx++;
2839 if (!*(args[myidx])) {
2840 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2841 file, linenum, args[myidx-1]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
2844 }
2845 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2846 if (err) {
2847 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2848 file, linenum, *err, args[myidx-1]);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851 }
2852 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002853 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002854 }
2855 else if (strcmp(args[myidx], "nopurge") == 0) {
2856 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002857 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002858 }
2859 else if (strcmp(args[myidx], "type") == 0) {
2860 myidx++;
2861 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2862 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2863 file, linenum, args[myidx]);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002867 /* myidx already points to next arg */
2868 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002869 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002870 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002871 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002872
2873 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002874 nw = args[myidx];
2875 while (*nw) {
2876 /* the "store" keyword supports a comma-separated list */
2877 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002878 sa = NULL; /* store arg */
2879 while (*nw && *nw != ',') {
2880 if (*nw == '(') {
2881 *nw = 0;
2882 sa = ++nw;
2883 while (*nw != ')') {
2884 if (!*nw) {
2885 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2886 file, linenum, args[0], cw);
2887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
2889 }
2890 nw++;
2891 }
2892 *nw = '\0';
2893 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002894 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002895 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002896 if (*nw)
2897 *nw++ = '\0';
2898 type = stktable_get_data_type(cw);
2899 if (type < 0) {
2900 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2901 file, linenum, args[0], cw);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
Willy Tarreauac782882010-06-20 10:41:54 +02002905
2906 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2907 switch (err) {
2908 case PE_NONE: break;
2909 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002910 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2911 file, linenum, args[0], cw);
2912 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002913 break;
2914
2915 case PE_ARG_MISSING:
2916 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2917 file, linenum, args[0], cw);
2918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
2920
2921 case PE_ARG_NOT_USED:
2922 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2923 file, linenum, args[0], cw);
2924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
2926
2927 default:
2928 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2929 file, linenum, args[0], cw);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002932 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002933 }
2934 myidx++;
2935 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002936 else {
2937 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2938 file, linenum, args[myidx]);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002941 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002942 }
2943
2944 if (!curproxy->table.size) {
2945 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2946 file, linenum);
2947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
2949 }
2950
2951 if (curproxy->table.type == (unsigned int)-1) {
2952 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2953 file, linenum);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
2956 }
2957 }
2958 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002959 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002960 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002961 int myidx = 0;
2962 const char *name = NULL;
2963 int flags;
2964
2965 if (curproxy == &defproxy) {
2966 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
2969 }
2970
2971 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2972 err_code |= ERR_WARN;
2973 goto out;
2974 }
2975
2976 myidx++;
2977 if ((strcmp(args[myidx], "store") == 0) ||
2978 (strcmp(args[myidx], "store-request") == 0)) {
2979 myidx++;
2980 flags = STK_IS_STORE;
2981 }
2982 else if (strcmp(args[myidx], "store-response") == 0) {
2983 myidx++;
2984 flags = STK_IS_STORE | STK_ON_RSP;
2985 }
2986 else if (strcmp(args[myidx], "match") == 0) {
2987 myidx++;
2988 flags = STK_IS_MATCH;
2989 }
2990 else if (strcmp(args[myidx], "on") == 0) {
2991 myidx++;
2992 flags = STK_IS_MATCH | STK_IS_STORE;
2993 }
2994 else {
2995 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999
3000 if (*(args[myidx]) == 0) {
3001 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
3004 }
3005
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003006 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003007 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003008 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003009 err_code |= ERR_ALERT | ERR_FATAL;
3010 goto out;
3011 }
3012
3013 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003014 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003015 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3016 file, linenum, args[0], expr->fetch->kw);
3017 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003018 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003019 goto out;
3020 }
3021 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003022 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003023 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3024 file, linenum, args[0], expr->fetch->kw);
3025 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003026 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 goto out;
3028 }
3029 }
3030
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003031 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3032 if (expr->fetch->cap & SMP_CAP_L7)
3033 curproxy->acl_requires |= ACL_USE_L7_ANY;
3034
Emeric Brunb982a3d2010-01-04 15:45:53 +01003035 if (strcmp(args[myidx], "table") == 0) {
3036 myidx++;
3037 name = args[myidx++];
3038 }
3039
Willy Tarreauef6494c2010-01-28 17:12:36 +01003040 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003041 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3042 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3043 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003044 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003045 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003046 goto out;
3047 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003049 else if (*(args[myidx])) {
3050 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3051 file, linenum, args[0], args[myidx]);
3052 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003053 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003054 goto out;
3055 }
Emeric Brun97679e72010-09-23 17:56:44 +02003056 if (flags & STK_ON_RSP)
3057 err_code |= warnif_cond_requires_req(cond, file, linenum);
3058 else
3059 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003060
Emeric Brunb982a3d2010-01-04 15:45:53 +01003061 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3062 rule->cond = cond;
3063 rule->expr = expr;
3064 rule->flags = flags;
3065 rule->table.name = name ? strdup(name) : NULL;
3066 LIST_INIT(&rule->list);
3067 if (flags & STK_ON_RSP)
3068 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3069 else
3070 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003073 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003075
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3077 curproxy->uri_auth = NULL; /* we must detach from the default config */
3078
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003079 if (!*args[1]) {
3080 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003081 } else if (!strcmp(args[1], "admin")) {
3082 struct stats_admin_rule *rule;
3083
3084 if (curproxy == &defproxy) {
3085 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
3088 }
3089
3090 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3091 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3092 err_code |= ERR_ALERT | ERR_ABORT;
3093 goto out;
3094 }
3095
3096 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3097 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3098 file, linenum, args[0], args[1]);
3099 err_code |= ERR_ALERT | ERR_FATAL;
3100 goto out;
3101 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003102 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3103 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3104 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
3107 }
3108
3109 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3110
3111 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3112 rule->cond = cond;
3113 LIST_INIT(&rule->list);
3114 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 } else if (!strcmp(args[1], "uri")) {
3116 if (*(args[2]) == 0) {
3117 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3121 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003122 err_code |= ERR_ALERT | ERR_ABORT;
3123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 }
3125 } else if (!strcmp(args[1], "realm")) {
3126 if (*(args[2]) == 0) {
3127 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3131 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003132 err_code |= ERR_ALERT | ERR_ABORT;
3133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003135 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003136 unsigned interval;
3137
3138 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3139 if (err) {
3140 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3141 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003144 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3145 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003146 err_code |= ERR_ALERT | ERR_ABORT;
3147 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003148 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003149 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003150 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003151
3152 if (curproxy == &defproxy) {
3153 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156 }
3157
3158 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3159 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3160 err_code |= ERR_ALERT | ERR_ABORT;
3161 goto out;
3162 }
3163
Willy Tarreauff011f22011-01-06 17:51:27 +01003164 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3165 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003166 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3167 file, linenum, args[0]);
3168 err_code |= ERR_WARN;
3169 }
3170
Willy Tarreauff011f22011-01-06 17:51:27 +01003171 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003172
Willy Tarreauff011f22011-01-06 17:51:27 +01003173 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003174 err_code |= ERR_ALERT | ERR_ABORT;
3175 goto out;
3176 }
3177
Willy Tarreauff011f22011-01-06 17:51:27 +01003178 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3179 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003180
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 } else if (!strcmp(args[1], "auth")) {
3182 if (*(args[2]) == 0) {
3183 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3187 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_ABORT;
3189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 }
3191 } else if (!strcmp(args[1], "scope")) {
3192 if (*(args[2]) == 0) {
3193 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3197 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_ALERT | ERR_ABORT;
3199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 }
3201 } else if (!strcmp(args[1], "enable")) {
3202 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3203 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_ABORT;
3205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003207 } else if (!strcmp(args[1], "hide-version")) {
3208 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3209 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003210 err_code |= ERR_ALERT | ERR_ABORT;
3211 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003212 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003213 } else if (!strcmp(args[1], "show-legends")) {
3214 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3215 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3216 err_code |= ERR_ALERT | ERR_ABORT;
3217 goto out;
3218 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003219 } else if (!strcmp(args[1], "show-node")) {
3220
3221 if (*args[2]) {
3222 int i;
3223 char c;
3224
3225 for (i=0; args[2][i]; i++) {
3226 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003227 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3228 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003229 break;
3230 }
3231
3232 if (!i || args[2][i]) {
3233 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3234 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3235 file, linenum, args[0], args[1]);
3236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
3238 }
3239 }
3240
3241 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3242 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3243 err_code |= ERR_ALERT | ERR_ABORT;
3244 goto out;
3245 }
3246 } else if (!strcmp(args[1], "show-desc")) {
3247 char *desc = NULL;
3248
3249 if (*args[2]) {
3250 int i, len=0;
3251 char *d;
3252
3253 for(i=2; *args[i]; i++)
3254 len += strlen(args[i])+1;
3255
3256 desc = d = (char *)calloc(1, len);
3257
3258 d += sprintf(d, "%s", args[2]);
3259 for(i=3; *args[i]; i++)
3260 d += sprintf(d, " %s", args[i]);
3261 }
3262
3263 if (!*args[2] && !global.desc)
3264 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3265 file, linenum, args[1]);
3266 else {
3267 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3268 free(desc);
3269 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3270 err_code |= ERR_ALERT | ERR_ABORT;
3271 goto out;
3272 }
3273 free(desc);
3274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003276stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003277 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 +01003278 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 }
3282 }
3283 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003284 int optnum;
3285
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003286 if (*(args[1]) == '\0') {
3287 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3288 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003292
3293 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3294 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003295 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3296 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3297 file, linenum, cfg_opts[optnum].name);
3298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
3300 }
Willy Tarreau93893792009-07-23 13:19:11 +02003301 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3302 err_code |= ERR_WARN;
3303 goto out;
3304 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003305
Willy Tarreau3842f002009-06-14 11:39:52 +02003306 curproxy->no_options &= ~cfg_opts[optnum].val;
3307 curproxy->options &= ~cfg_opts[optnum].val;
3308
3309 switch (kwm) {
3310 case KWM_STD:
3311 curproxy->options |= cfg_opts[optnum].val;
3312 break;
3313 case KWM_NO:
3314 curproxy->no_options |= cfg_opts[optnum].val;
3315 break;
3316 case KWM_DEF: /* already cleared */
3317 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003318 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003319
Willy Tarreau93893792009-07-23 13:19:11 +02003320 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003321 }
3322 }
3323
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003324 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3325 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003326 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3327 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3328 file, linenum, cfg_opts2[optnum].name);
3329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
3331 }
Willy Tarreau93893792009-07-23 13:19:11 +02003332 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3333 err_code |= ERR_WARN;
3334 goto out;
3335 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003336
Willy Tarreau3842f002009-06-14 11:39:52 +02003337 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3338 curproxy->options2 &= ~cfg_opts2[optnum].val;
3339
3340 switch (kwm) {
3341 case KWM_STD:
3342 curproxy->options2 |= cfg_opts2[optnum].val;
3343 break;
3344 case KWM_NO:
3345 curproxy->no_options2 |= cfg_opts2[optnum].val;
3346 break;
3347 case KWM_DEF: /* already cleared */
3348 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003349 }
Willy Tarreau93893792009-07-23 13:19:11 +02003350 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003351 }
3352 }
3353
Willy Tarreau3842f002009-06-14 11:39:52 +02003354 if (kwm != KWM_STD) {
3355 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003356 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003359 }
3360
Emeric Brun3a058f32009-06-30 18:26:00 +02003361 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003362 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003364 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003365 if (*(args[2]) != '\0') {
3366 if (!strcmp(args[2], "clf")) {
3367 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003368 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003369 } else {
3370 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003373 }
3374 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003375 if (curproxy->logformat_string != default_http_log_format &&
3376 curproxy->logformat_string != default_tcp_log_format &&
3377 curproxy->logformat_string != clf_http_log_format)
3378 free(curproxy->logformat_string);
3379 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003380 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003381 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003383 if (curproxy->logformat_string != default_http_log_format &&
3384 curproxy->logformat_string != default_tcp_log_format &&
3385 curproxy->logformat_string != clf_http_log_format)
3386 free(curproxy->logformat_string);
3387 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 else if (!strcmp(args[1], "tcpka")) {
3390 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003391 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003393
3394 if (curproxy->cap & PR_CAP_FE)
3395 curproxy->options |= PR_O_TCP_CLI_KA;
3396 if (curproxy->cap & PR_CAP_BE)
3397 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 }
3399 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003400 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_WARN;
3402
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003404 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003405 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003406 curproxy->options2 &= ~PR_O2_CHK_ANY;
3407 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 if (!*args[2]) { /* no argument */
3409 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3410 curproxy->check_len = strlen(DEF_CHECK_REQ);
3411 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003412 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 curproxy->check_req = (char *)malloc(reqlen);
3414 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003415 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003417 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 if (*args[4])
3419 reqlen += strlen(args[4]);
3420 else
3421 reqlen += strlen("HTTP/1.0");
3422
3423 curproxy->check_req = (char *)malloc(reqlen);
3424 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003425 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003427 }
3428 else if (!strcmp(args[1], "ssl-hello-chk")) {
3429 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003430 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003431 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003432
Willy Tarreaua534fea2008-08-03 12:19:50 +02003433 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003434 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003435 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003436 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 }
Willy Tarreau23677902007-05-08 23:50:35 +02003438 else if (!strcmp(args[1], "smtpchk")) {
3439 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003440 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003441 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003442 curproxy->options2 &= ~PR_O2_CHK_ANY;
3443 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003444
3445 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3446 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3447 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3448 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3449 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3450 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3451 curproxy->check_req = (char *)malloc(reqlen);
3452 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3453 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3454 } else {
3455 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3456 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3457 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3458 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3459 }
3460 }
3461 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003462 else if (!strcmp(args[1], "pgsql-check")) {
3463 /* use PostgreSQL request to check servers' health */
3464 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3465 err_code |= ERR_WARN;
3466
3467 free(curproxy->check_req);
3468 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003469 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003470 curproxy->options2 |= PR_O2_PGSQL_CHK;
3471
3472 if (*(args[2])) {
3473 int cur_arg = 2;
3474
3475 while (*(args[cur_arg])) {
3476 if (strcmp(args[cur_arg], "user") == 0) {
3477 char * packet;
3478 uint32_t packet_len;
3479 uint32_t pv;
3480
3481 /* suboption header - needs additional argument for it */
3482 if (*(args[cur_arg+1]) == 0) {
3483 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3484 file, linenum, args[0], args[1], args[cur_arg]);
3485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
3487 }
3488
3489 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3490 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3491 pv = htonl(0x30000); /* protocol version 3.0 */
3492
3493 packet = (char*) calloc(1, packet_len);
3494
3495 memcpy(packet + 4, &pv, 4);
3496
3497 /* copy "user" */
3498 memcpy(packet + 8, "user", 4);
3499
3500 /* copy username */
3501 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3502
3503 free(curproxy->check_req);
3504 curproxy->check_req = packet;
3505 curproxy->check_len = packet_len;
3506
3507 packet_len = htonl(packet_len);
3508 memcpy(packet, &packet_len, 4);
3509 cur_arg += 2;
3510 } else {
3511 /* unknown suboption - catchall */
3512 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3513 file, linenum, args[0], args[1]);
3514 err_code |= ERR_ALERT | ERR_FATAL;
3515 goto out;
3516 }
3517 } /* end while loop */
3518 }
3519 }
3520
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003521 else if (!strcmp(args[1], "redis-check")) {
3522 /* use REDIS PING request to check servers' health */
3523 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3524 err_code |= ERR_WARN;
3525
3526 free(curproxy->check_req);
3527 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003528 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003529 curproxy->options2 |= PR_O2_REDIS_CHK;
3530
3531 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3532 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3533 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3534 }
3535
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003536 else if (!strcmp(args[1], "mysql-check")) {
3537 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003538 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3539 err_code |= ERR_WARN;
3540
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003541 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003542 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003543 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003544 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003545
3546 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3547 * const char mysql40_client_auth_pkt[] = {
3548 * "\x0e\x00\x00" // packet length
3549 * "\x01" // packet number
3550 * "\x00\x00" // client capabilities
3551 * "\x00\x00\x01" // max packet
3552 * "haproxy\x00" // username (null terminated string)
3553 * "\x00" // filler (always 0x00)
3554 * "\x01\x00\x00" // packet length
3555 * "\x00" // packet number
3556 * "\x01" // COM_QUIT command
3557 * };
3558 */
3559
3560 if (*(args[2])) {
3561 int cur_arg = 2;
3562
3563 while (*(args[cur_arg])) {
3564 if (strcmp(args[cur_arg], "user") == 0) {
3565 char *mysqluser;
3566 int packetlen, reqlen, userlen;
3567
3568 /* suboption header - needs additional argument for it */
3569 if (*(args[cur_arg+1]) == 0) {
3570 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3571 file, linenum, args[0], args[1], args[cur_arg]);
3572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
3574 }
3575 mysqluser = args[cur_arg + 1];
3576 userlen = strlen(mysqluser);
3577 packetlen = userlen + 7;
3578 reqlen = packetlen + 9;
3579
3580 free(curproxy->check_req);
3581 curproxy->check_req = (char *)calloc(1, reqlen);
3582 curproxy->check_len = reqlen;
3583
3584 snprintf(curproxy->check_req, 4, "%c%c%c",
3585 ((unsigned char) packetlen & 0xff),
3586 ((unsigned char) (packetlen >> 8) & 0xff),
3587 ((unsigned char) (packetlen >> 16) & 0xff));
3588
3589 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003590 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003591 curproxy->check_req[8] = 1;
3592 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3593 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3594 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3595 cur_arg += 2;
3596 } else {
3597 /* unknown suboption - catchall */
3598 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3599 file, linenum, args[0], args[1]);
3600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
3602 }
3603 } /* end while loop */
3604 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003605 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003606 else if (!strcmp(args[1], "ldap-check")) {
3607 /* use LDAP request to check servers' health */
3608 free(curproxy->check_req);
3609 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003610 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003611 curproxy->options2 |= PR_O2_LDAP_CHK;
3612
3613 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3614 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3615 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3616 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003617 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003618 int cur_arg;
3619
3620 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3621 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003622 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003623
Willy Tarreau87cf5142011-08-19 22:57:24 +02003624 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003625
3626 free(curproxy->fwdfor_hdr_name);
3627 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3628 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3629
3630 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3631 cur_arg = 2;
3632 while (*(args[cur_arg])) {
3633 if (!strcmp(args[cur_arg], "except")) {
3634 /* suboption except - needs additional argument for it */
3635 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3636 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3637 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003638 err_code |= ERR_ALERT | ERR_FATAL;
3639 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003640 }
3641 /* flush useless bits */
3642 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003643 cur_arg += 2;
3644 } else if (!strcmp(args[cur_arg], "header")) {
3645 /* suboption header - needs additional argument for it */
3646 if (*(args[cur_arg+1]) == 0) {
3647 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3648 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003651 }
3652 free(curproxy->fwdfor_hdr_name);
3653 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3654 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3655 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003656 } else if (!strcmp(args[cur_arg], "if-none")) {
3657 curproxy->options &= ~PR_O_FF_ALWAYS;
3658 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003659 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003660 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003661 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003662 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003665 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003666 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003667 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003668 else if (!strcmp(args[1], "originalto")) {
3669 int cur_arg;
3670
3671 /* insert x-original-to field, but not for the IP address listed as an except.
3672 * set default options (ie: bitfield, header name, etc)
3673 */
3674
3675 curproxy->options |= PR_O_ORGTO;
3676
3677 free(curproxy->orgto_hdr_name);
3678 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3679 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3680
Willy Tarreau87cf5142011-08-19 22:57:24 +02003681 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003682 cur_arg = 2;
3683 while (*(args[cur_arg])) {
3684 if (!strcmp(args[cur_arg], "except")) {
3685 /* suboption except - needs additional argument for it */
3686 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3687 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3688 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003691 }
3692 /* flush useless bits */
3693 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3694 cur_arg += 2;
3695 } else if (!strcmp(args[cur_arg], "header")) {
3696 /* suboption header - needs additional argument for it */
3697 if (*(args[cur_arg+1]) == 0) {
3698 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3699 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003702 }
3703 free(curproxy->orgto_hdr_name);
3704 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3705 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3706 cur_arg += 2;
3707 } else {
3708 /* unknown suboption - catchall */
3709 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3710 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003713 }
3714 } /* end while loop */
3715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 else {
3717 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003720 }
Willy Tarreau93893792009-07-23 13:19:11 +02003721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003723 else if (!strcmp(args[0], "default_backend")) {
3724 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003726
3727 if (*(args[1]) == 0) {
3728 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003731 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003732 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003733 curproxy->defbe.name = strdup(args[1]);
3734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003736 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003738
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003739 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3740 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 /* enable reconnections to dispatch */
3743 curproxy->options |= PR_O_REDISP;
3744 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003745 else if (!strcmp(args[0], "http-check")) {
3746 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003748
3749 if (strcmp(args[1], "disable-on-404") == 0) {
3750 /* enable a graceful server shutdown on an HTTP 404 response */
3751 curproxy->options |= PR_O_DISABLE404;
3752 }
Willy Tarreauef781042010-01-27 11:53:01 +01003753 else if (strcmp(args[1], "send-state") == 0) {
3754 /* enable emission of the apparent state of a server in HTTP checks */
3755 curproxy->options2 |= PR_O2_CHK_SNDST;
3756 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003757 else if (strcmp(args[1], "expect") == 0) {
3758 const char *ptr_arg;
3759 int cur_arg;
3760
3761 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3762 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
3765 }
3766
3767 cur_arg = 2;
3768 /* consider exclamation marks, sole or at the beginning of a word */
3769 while (*(ptr_arg = args[cur_arg])) {
3770 while (*ptr_arg == '!') {
3771 curproxy->options2 ^= PR_O2_EXP_INV;
3772 ptr_arg++;
3773 }
3774 if (*ptr_arg)
3775 break;
3776 cur_arg++;
3777 }
3778 /* now ptr_arg points to the beginning of a word past any possible
3779 * exclamation mark, and cur_arg is the argument which holds this word.
3780 */
3781 if (strcmp(ptr_arg, "status") == 0) {
3782 if (!*(args[cur_arg + 1])) {
3783 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3784 file, linenum, args[0], args[1], ptr_arg);
3785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
3787 }
3788 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003789 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003790 curproxy->expect_str = strdup(args[cur_arg + 1]);
3791 }
3792 else if (strcmp(ptr_arg, "string") == 0) {
3793 if (!*(args[cur_arg + 1])) {
3794 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3795 file, linenum, args[0], args[1], ptr_arg);
3796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
3798 }
3799 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003800 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003801 curproxy->expect_str = strdup(args[cur_arg + 1]);
3802 }
3803 else if (strcmp(ptr_arg, "rstatus") == 0) {
3804 if (!*(args[cur_arg + 1])) {
3805 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3806 file, linenum, args[0], args[1], ptr_arg);
3807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
3809 }
3810 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003811 free(curproxy->expect_str);
3812 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3813 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003814 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3815 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3816 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3817 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
3820 }
3821 }
3822 else if (strcmp(ptr_arg, "rstring") == 0) {
3823 if (!*(args[cur_arg + 1])) {
3824 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3825 file, linenum, args[0], args[1], ptr_arg);
3826 err_code |= ERR_ALERT | ERR_FATAL;
3827 goto out;
3828 }
3829 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003830 free(curproxy->expect_str);
3831 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3832 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003833 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3834 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3835 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3836 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3837 err_code |= ERR_ALERT | ERR_FATAL;
3838 goto out;
3839 }
3840 }
3841 else {
3842 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3843 file, linenum, args[0], args[1], ptr_arg);
3844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
3846 }
3847 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003848 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003849 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 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003852 }
3853 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003854 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003855 if (curproxy == &defproxy) {
3856 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003859 }
3860
Willy Tarreaub80c2302007-11-30 20:51:32 +01003861 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003863
3864 if (strcmp(args[1], "fail") == 0) {
3865 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003866 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003867 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3868 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003869 err_code |= ERR_ALERT | ERR_FATAL;
3870 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003871 }
3872
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003873 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3874 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3875 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003878 }
3879 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3880 }
3881 else {
3882 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003885 }
3886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887#ifdef TPROXY
3888 else if (!strcmp(args[0], "transparent")) {
3889 /* enable transparent proxy connections */
3890 curproxy->options |= PR_O_TRANSP;
3891 }
3892#endif
3893 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003894 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003895 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003896
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897 if (*(args[1]) == 0) {
3898 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003901 }
3902 curproxy->maxconn = atol(args[1]);
3903 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003904 else if (!strcmp(args[0], "backlog")) { /* backlog */
3905 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003907
3908 if (*(args[1]) == 0) {
3909 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003912 }
3913 curproxy->backlog = atol(args[1]);
3914 }
Willy Tarreau86034312006-12-29 00:10:33 +01003915 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003916 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003918
Willy Tarreau86034312006-12-29 00:10:33 +01003919 if (*(args[1]) == 0) {
3920 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003923 }
3924 curproxy->fullconn = atol(args[1]);
3925 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3927 if (*(args[1]) == 0) {
3928 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003932 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3933 if (err) {
3934 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3935 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003938 }
3939 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003940 }
3941 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003942 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 if (curproxy == &defproxy) {
3944 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003948 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003949 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003950
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 if (strchr(args[1], ':') == NULL) {
3952 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003955 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003956 sk = str2sa(args[1]);
3957 if (!sk) {
3958 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
3962 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003963 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 }
3965 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003966 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003968
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003969 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3970 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003974 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003975 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3976 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3977 err_code |= ERR_WARN;
3978
3979 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3980 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3981 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3982 }
3983 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3984 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3985 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3986 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003987 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3988 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3989 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3990 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003991 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003992 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 }
3996 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003997 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003998 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003999 char *rport, *raddr;
4000 short realport = 0;
4001 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004003 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004008 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004009 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010
4011 if (!*args[2]) {
4012 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4013 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004016 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004017
4018 err = invalid_char(args[1]);
4019 if (err) {
4020 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4021 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004024 }
4025
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004026 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004027 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004028
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004029 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4030 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4031 err_code |= ERR_ALERT | ERR_ABORT;
4032 goto out;
4033 }
4034
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004035 /* the servers are linked backwards first */
4036 newsrv->next = curproxy->srv;
4037 curproxy->srv = newsrv;
4038 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004039 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004040 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004042 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004043 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004044 LIST_INIT(&newsrv->pendconns);
4045 do_check = 0;
4046 newsrv->state = SRV_RUNNING; /* early server setup */
4047 newsrv->last_change = now.tv_sec;
4048 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004050 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004051 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004052 * - IP: => port=+0, relative
4053 * - IP:N => port=N, absolute
4054 * - IP:+N => port=+N, relative
4055 * - IP:-N => port=-N, relative
4056 */
4057 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004058 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004059 if (rport) {
4060 *rport++ = 0;
4061 realport = atol(rport);
4062 if (!isdigit((unsigned char)*rport))
4063 newsrv->state |= SRV_MAPPORTS;
4064 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004066
Willy Tarreaufab5a432011-03-04 15:31:53 +01004067 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004068 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004069 if (!sk) {
4070 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
4074 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004075 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4076 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004077
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004078 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004079 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4080 file, linenum, newsrv->addr.ss_family, args[2]);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004084 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004085
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004086 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004087 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004088 newsrv->inter = curproxy->defsrv.inter;
4089 newsrv->fastinter = curproxy->defsrv.fastinter;
4090 newsrv->downinter = curproxy->defsrv.downinter;
4091 newsrv->rise = curproxy->defsrv.rise;
4092 newsrv->fall = curproxy->defsrv.fall;
4093 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4094 newsrv->minconn = curproxy->defsrv.minconn;
4095 newsrv->maxconn = curproxy->defsrv.maxconn;
4096 newsrv->slowstart = curproxy->defsrv.slowstart;
4097 newsrv->onerror = curproxy->defsrv.onerror;
4098 newsrv->consecutive_errors_limit
4099 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004100#ifdef OPENSSL
4101 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4102#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004103 newsrv->uweight = newsrv->iweight
4104 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004105
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004106 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004107
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004108 cur_arg = 3;
4109 } else {
4110 newsrv = &curproxy->defsrv;
4111 cur_arg = 1;
4112 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004113
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004115 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004116 newsrv->cookie = strdup(args[cur_arg + 1]);
4117 newsrv->cklen = strlen(args[cur_arg + 1]);
4118 cur_arg += 2;
4119 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004120 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004121 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4122 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4123 cur_arg += 2;
4124 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004126 if (!*args[cur_arg + 1]) {
4127 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4128 file, linenum, args[cur_arg]);
4129 err_code |= ERR_ALERT | ERR_FATAL;
4130 goto out;
4131 }
4132
Willy Tarreaubaaee002006-06-26 02:48:02 +02004133 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004134 if (newsrv->rise <= 0) {
4135 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4136 file, linenum, args[cur_arg]);
4137 err_code |= ERR_ALERT | ERR_FATAL;
4138 goto out;
4139 }
4140
Willy Tarreau96839092010-03-29 10:02:24 +02004141 if (newsrv->health)
4142 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004143 cur_arg += 2;
4144 }
4145 else if (!strcmp(args[cur_arg], "fall")) {
4146 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004147
4148 if (!*args[cur_arg + 1]) {
4149 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4150 file, linenum, args[cur_arg]);
4151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
4153 }
4154
4155 if (newsrv->fall <= 0) {
4156 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4157 file, linenum, args[cur_arg]);
4158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
4160 }
4161
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 cur_arg += 2;
4163 }
4164 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004165 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4166 if (err) {
4167 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4168 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004171 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004172 if (val <= 0) {
4173 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4174 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004177 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004178 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 cur_arg += 2;
4180 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004181 else if (!strcmp(args[cur_arg], "fastinter")) {
4182 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4183 if (err) {
4184 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4185 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004188 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004189 if (val <= 0) {
4190 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4191 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004194 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004195 newsrv->fastinter = val;
4196 cur_arg += 2;
4197 }
4198 else if (!strcmp(args[cur_arg], "downinter")) {
4199 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4200 if (err) {
4201 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4202 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004205 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004206 if (val <= 0) {
4207 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4208 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004209 err_code |= ERR_ALERT | ERR_FATAL;
4210 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004211 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004212 newsrv->downinter = val;
4213 cur_arg += 2;
4214 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004215 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004216 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004217 if (!sk) {
4218 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
4221 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004222 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004223 cur_arg += 2;
4224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004226 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 cur_arg += 2;
4228 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004229 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230 newsrv->state |= SRV_BACKUP;
4231 cur_arg ++;
4232 }
Simon Hormanfa461682011-06-25 09:39:49 +09004233 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4234 newsrv->state |= SRV_NON_STICK;
4235 cur_arg ++;
4236 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004237 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4238 newsrv->state |= SRV_SEND_PROXY;
4239 cur_arg ++;
4240 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004241 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4242 newsrv->check.send_proxy = 1;
4243 cur_arg ++;
4244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004245 else if (!strcmp(args[cur_arg], "weight")) {
4246 int w;
4247 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004248 if (w < 0 || w > 256) {
4249 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004253 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004254 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 cur_arg += 2;
4256 }
4257 else if (!strcmp(args[cur_arg], "minconn")) {
4258 newsrv->minconn = atol(args[cur_arg + 1]);
4259 cur_arg += 2;
4260 }
4261 else if (!strcmp(args[cur_arg], "maxconn")) {
4262 newsrv->maxconn = atol(args[cur_arg + 1]);
4263 cur_arg += 2;
4264 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004265 else if (!strcmp(args[cur_arg], "maxqueue")) {
4266 newsrv->maxqueue = atol(args[cur_arg + 1]);
4267 cur_arg += 2;
4268 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004269 else if (!strcmp(args[cur_arg], "slowstart")) {
4270 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004271 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004272 if (err) {
4273 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4274 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004277 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004278 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004279 cur_arg += 2;
4280 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004281 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004282
4283 if (!*args[cur_arg + 1]) {
4284 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4285 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004288 }
4289
4290 newsrv->trackit = strdup(args[cur_arg + 1]);
4291
4292 cur_arg += 2;
4293 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004294 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 global.maxsock++;
4296 do_check = 1;
4297 cur_arg += 1;
4298 }
Willy Tarreau96839092010-03-29 10:02:24 +02004299 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4300 newsrv->state |= SRV_MAINTAIN;
4301 newsrv->state &= ~SRV_RUNNING;
4302 newsrv->health = 0;
4303 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004304 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004305 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004306 if (!strcmp(args[cur_arg + 1], "none"))
4307 newsrv->observe = HANA_OBS_NONE;
4308 else if (!strcmp(args[cur_arg + 1], "layer4"))
4309 newsrv->observe = HANA_OBS_LAYER4;
4310 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4311 if (curproxy->mode != PR_MODE_HTTP) {
4312 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4313 file, linenum, args[cur_arg + 1]);
4314 err_code |= ERR_ALERT;
4315 }
4316 newsrv->observe = HANA_OBS_LAYER7;
4317 }
4318 else {
4319 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004320 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004321 file, linenum, args[cur_arg], args[cur_arg + 1]);
4322 err_code |= ERR_ALERT | ERR_FATAL;
4323 goto out;
4324 }
4325
4326 cur_arg += 2;
4327 }
4328 else if (!strcmp(args[cur_arg], "on-error")) {
4329 if (!strcmp(args[cur_arg + 1], "fastinter"))
4330 newsrv->onerror = HANA_ONERR_FASTINTER;
4331 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4332 newsrv->onerror = HANA_ONERR_FAILCHK;
4333 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4334 newsrv->onerror = HANA_ONERR_SUDDTH;
4335 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4336 newsrv->onerror = HANA_ONERR_MARKDWN;
4337 else {
4338 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004339 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004340 file, linenum, args[cur_arg], args[cur_arg + 1]);
4341 err_code |= ERR_ALERT | ERR_FATAL;
4342 goto out;
4343 }
4344
4345 cur_arg += 2;
4346 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004347 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4348 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4349 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4350 else {
4351 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4352 file, linenum, args[cur_arg], args[cur_arg + 1]);
4353 err_code |= ERR_ALERT | ERR_FATAL;
4354 goto out;
4355 }
4356
4357 cur_arg += 2;
4358 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004359 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4360 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4361 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4362 else {
4363 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4364 file, linenum, args[cur_arg], args[cur_arg + 1]);
4365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
4367 }
4368
4369 cur_arg += 2;
4370 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004371 else if (!strcmp(args[cur_arg], "error-limit")) {
4372 if (!*args[cur_arg + 1]) {
4373 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4374 file, linenum, args[cur_arg]);
4375 err_code |= ERR_ALERT | ERR_FATAL;
4376 goto out;
4377 }
4378
4379 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4380
4381 if (newsrv->consecutive_errors_limit <= 0) {
4382 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4383 file, linenum, args[cur_arg]);
4384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
4386 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004387 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004388 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004389 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004390 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004391 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004392
Willy Tarreaubaaee002006-06-26 02:48:02 +02004393 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004394 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4395 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004399 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004400 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4401 if (!sk) {
4402 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
4405 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004406 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004407
4408 if (port_low != port_high) {
4409 int i;
4410 if (port_low <= 0 || port_low > 65535 ||
4411 port_high <= 0 || port_high > 65535 ||
4412 port_low > port_high) {
4413 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4414 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004417 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004418 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4419 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4420 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004421 }
4422
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004424 while (*(args[cur_arg])) {
4425 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004426#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4427#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004428 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004429 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4430 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004433 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004434#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004435 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004436 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004437 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004440 }
4441 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004442 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4443 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004444 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004445 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4446 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004447 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4448 char *name, *end;
4449
4450 name = args[cur_arg+1] + 7;
4451 while (isspace(*name))
4452 name++;
4453
4454 end = name;
4455 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4456 end++;
4457
Willy Tarreauef9a3602012-12-08 22:29:20 +01004458 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4459 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4460 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4461 newsrv->conn_src.bind_hdr_len = end - name;
4462 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4463 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4464 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004465
4466 /* now look for an occurrence number */
4467 while (isspace(*end))
4468 end++;
4469 if (*end == ',') {
4470 end++;
4471 name = end;
4472 if (*end == '-')
4473 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004474 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004475 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004476 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004477 }
4478
Willy Tarreauef9a3602012-12-08 22:29:20 +01004479 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004480 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4481 " occurrences values smaller than %d.\n",
4482 file, linenum, MAX_HDR_HISTORY);
4483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
4485 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004486 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004487 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004488 if (!sk) {
4489 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
4492 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004493 newsrv->conn_src.tproxy_addr = *sk;
4494 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004495 }
4496 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004497#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004498 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004499#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004500 cur_arg += 2;
4501 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004502#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004503 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004504 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004507#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4508 } /* "usesrc" */
4509
4510 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4511#ifdef SO_BINDTODEVICE
4512 if (!*args[cur_arg + 1]) {
4513 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4514 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004515 err_code |= ERR_ALERT | ERR_FATAL;
4516 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004517 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004518 free(newsrv->conn_src.iface_name);
4519 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4520 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004521 global.last_checks |= LSTCHK_NETADM;
4522#else
4523 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4524 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004527#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004528 cur_arg += 2;
4529 continue;
4530 }
4531 /* this keyword in not an option of "source" */
4532 break;
4533 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004534 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004535 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004536 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4537 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004538 err_code |= ERR_ALERT | ERR_FATAL;
4539 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004542 static int srv_dumped;
4543 struct srv_kw *kw;
4544 char *err;
4545
4546 kw = srv_find_kw(args[cur_arg]);
4547 if (kw) {
4548 char *err = NULL;
4549 int code;
4550
4551 if (!kw->parse) {
4552 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4553 file, linenum, args[0], args[1], args[cur_arg]);
4554 cur_arg += 1 + kw->skip ;
4555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
4557 }
4558
4559 if (defsrv && !kw->default_ok) {
4560 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4561 file, linenum, args[0], args[1], args[cur_arg]);
4562 cur_arg += 1 + kw->skip ;
4563 err_code |= ERR_ALERT;
4564 continue;
4565 }
4566
4567 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4568 err_code |= code;
4569
4570 if (code) {
4571 if (err && *err) {
4572 indent_msg(&err, 2);
4573 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4574 }
4575 else
4576 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4577 file, linenum, args[0], args[1], args[cur_arg]);
4578 if (code & ERR_FATAL) {
4579 free(err);
4580 cur_arg += 1 + kw->skip;
4581 goto out;
4582 }
4583 }
4584 free(err);
4585 cur_arg += 1 + kw->skip;
4586 continue;
4587 }
4588
4589 err = NULL;
4590 if (!srv_dumped) {
4591 srv_dump_kws(&err);
4592 indent_msg(&err, 4);
4593 srv_dumped = 1;
4594 }
4595
4596 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4597 file, linenum, args[0], args[1], args[cur_arg],
4598 err ? " Registered keywords :" : "", err ? err : "");
4599 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004600
Willy Tarreau93893792009-07-23 13:19:11 +02004601 err_code |= ERR_ALERT | ERR_FATAL;
4602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 }
4604 }
4605
4606 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004607 if (newsrv->trackit) {
4608 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4609 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004612 }
4613
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004614 /* If neither a port nor an addr was specified and no check transport
4615 * layer is forced, then the transport layer used by the checks is the
4616 * same as for the production traffic. Otherwise we use raw_sock by
4617 * default, unless one is specified.
4618 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004619 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004620#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004621 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004622#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004623 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4624 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004625 /* try to get the port from check.addr if check.port not set */
4626 if (!newsrv->check.port)
4627 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004628
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004629 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4630 newsrv->check.port = realport; /* by default */
4631 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004632 /* not yet valid, because no port was set on
4633 * the server either. We'll check if we have
4634 * a known port on the first listener.
4635 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004636 struct listener *l;
4637
4638 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004639 newsrv->check.port = get_host_port(&l->addr);
4640 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004641 break;
4642 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004643 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004644 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004645 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4646 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004650
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004651 /* Allocate buffer for check requests... */
4652 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004653 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4654 err_code |= ERR_ALERT | ERR_ABORT;
4655 goto out;
4656 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004657 newsrv->check.bi->size = global.tune.chksize;
4658
4659 /* Allocate buffer for check responses... */
4660 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4661 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4662 err_code |= ERR_ALERT | ERR_ABORT;
4663 goto out;
4664 }
4665 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004666
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004667 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004668 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004669 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4670 err_code |= ERR_ALERT | ERR_ABORT;
4671 goto out;
4672 }
4673
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004674 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4675 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 newsrv->state |= SRV_CHECKED;
4677 }
4678
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004679 if (!defsrv) {
4680 if (newsrv->state & SRV_BACKUP)
4681 curproxy->srv_bck++;
4682 else
4683 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004684
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004685 newsrv->prev_state = newsrv->state;
4686 }
William Lallemanda73203e2012-03-12 12:48:57 +01004687 }
4688
4689 else if (strcmp(args[0], "unique-id-format") == 0) {
4690 if (!*(args[1])) {
4691 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4692 err_code |= ERR_ALERT | ERR_FATAL;
4693 goto out;
4694 }
William Lallemand3203ff42012-11-11 17:30:56 +01004695 if (*(args[2])) {
4696 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
4699 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004700 free(curproxy->uniqueid_format_string);
4701 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004702 }
William Lallemanda73203e2012-03-12 12:48:57 +01004703
4704 else if (strcmp(args[0], "unique-id-header") == 0) {
4705 if (!*(args[1])) {
4706 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
4709 }
4710 free(curproxy->header_unique_id);
4711 curproxy->header_unique_id = strdup(args[1]);
4712 }
4713
William Lallemand723b73a2012-02-08 16:37:49 +01004714 else if (strcmp(args[0], "log-format") == 0) {
4715 if (!*(args[1])) {
4716 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4717 err_code |= ERR_ALERT | ERR_FATAL;
4718 goto out;
4719 }
William Lallemand3203ff42012-11-11 17:30:56 +01004720 if (*(args[2])) {
4721 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004725
4726 if (curproxy->logformat_string != default_http_log_format &&
4727 curproxy->logformat_string != default_tcp_log_format &&
4728 curproxy->logformat_string != clf_http_log_format)
4729 free(curproxy->logformat_string);
4730 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 }
William Lallemand723b73a2012-02-08 16:37:49 +01004732
William Lallemand0f99e342011-10-12 17:50:54 +02004733 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4734 /* delete previous herited or defined syslog servers */
4735 struct logsrv *back;
4736
4737 if (*(args[1]) != 0) {
4738 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4739 err_code |= ERR_ALERT | ERR_FATAL;
4740 goto out;
4741 }
4742
William Lallemand723b73a2012-02-08 16:37:49 +01004743 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4744 LIST_DEL(&tmplogsrv->list);
4745 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004746 }
4747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004749 struct logsrv *logsrv;
4750
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004752 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004753 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004754 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004755 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004756 LIST_INIT(&node->list);
4757 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759 }
4760 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004761
4762 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763
William Lallemand0f99e342011-10-12 17:50:54 +02004764 logsrv->facility = get_log_facility(args[2]);
4765 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004766 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004767 err_code |= ERR_ALERT | ERR_FATAL;
4768 goto out;
4769
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770 }
4771
William Lallemand0f99e342011-10-12 17:50:54 +02004772 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004774 logsrv->level = get_log_level(args[3]);
4775 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
4779
Willy Tarreaubaaee002006-06-26 02:48:02 +02004780 }
4781 }
4782
William Lallemand0f99e342011-10-12 17:50:54 +02004783 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004784 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004785 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004786 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004787 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004788 err_code |= ERR_ALERT | ERR_FATAL;
4789 goto out;
4790
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004791 }
4792 }
4793
Robert Tsai81ae1952007-12-05 10:47:29 +01004794 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004795 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004796 if (!sk) {
4797 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004798 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
4801 }
William Lallemand0f99e342011-10-12 17:50:54 +02004802 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004803 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004804 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004805 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004806 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
4809 }
William Lallemand0f99e342011-10-12 17:50:54 +02004810 logsrv->addr = *sk;
4811 if (!get_host_port(&logsrv->addr))
4812 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 }
William Lallemand0f99e342011-10-12 17:50:54 +02004814
4815 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004816 }
4817 else {
4818 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4819 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822 }
4823 }
4824 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004825 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004826 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004827
Willy Tarreau977b8e42006-12-29 14:19:17 +01004828 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004829 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004830
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004832 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4833 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004837
4838 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004839 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4840 free(curproxy->conn_src.iface_name);
4841 curproxy->conn_src.iface_name = NULL;
4842 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004843
Willy Tarreaud5191e72010-02-09 20:50:45 +01004844 sk = str2sa(args[1]);
4845 if (!sk) {
4846 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
4849 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004850 curproxy->conn_src.source_addr = *sk;
4851 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004852
4853 cur_arg = 2;
4854 while (*(args[cur_arg])) {
4855 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004856#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4857#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004858 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004859 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4860 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004863 }
4864#endif
4865 if (!*args[cur_arg + 1]) {
4866 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4867 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004870 }
4871
4872 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004873 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4874 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004875 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004876 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4877 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004878 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4879 char *name, *end;
4880
4881 name = args[cur_arg+1] + 7;
4882 while (isspace(*name))
4883 name++;
4884
4885 end = name;
4886 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4887 end++;
4888
Willy Tarreauef9a3602012-12-08 22:29:20 +01004889 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4890 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4891 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4892 curproxy->conn_src.bind_hdr_len = end - name;
4893 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4894 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4895 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004896
4897 /* now look for an occurrence number */
4898 while (isspace(*end))
4899 end++;
4900 if (*end == ',') {
4901 end++;
4902 name = end;
4903 if (*end == '-')
4904 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004905 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004906 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004907 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004908 }
4909
Willy Tarreauef9a3602012-12-08 22:29:20 +01004910 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004911 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4912 " occurrences values smaller than %d.\n",
4913 file, linenum, MAX_HDR_HISTORY);
4914 err_code |= ERR_ALERT | ERR_FATAL;
4915 goto out;
4916 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004917 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004918 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004919 if (!sk) {
4920 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
4923 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004924 curproxy->conn_src.tproxy_addr = *sk;
4925 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004926 }
4927 global.last_checks |= LSTCHK_NETADM;
4928#if !defined(CONFIG_HAP_LINUX_TPROXY)
4929 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004930#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004931#else /* no TPROXY support */
4932 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004933 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004936#endif
4937 cur_arg += 2;
4938 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004939 }
4940
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004941 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4942#ifdef SO_BINDTODEVICE
4943 if (!*args[cur_arg + 1]) {
4944 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4945 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004948 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004949 free(curproxy->conn_src.iface_name);
4950 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4951 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004952 global.last_checks |= LSTCHK_NETADM;
4953#else
4954 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4955 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004958#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004959 cur_arg += 2;
4960 continue;
4961 }
4962 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004963 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004968 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4969 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4970 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4977 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981
4982 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004983 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004984 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004985 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 }
4988 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004989 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004990 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004991 args[0], args[1], NULL, (const char **)args+2);
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], "reqdeny")) { /* deny a request if a header matches this regex */
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_DENY, 0,
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], "reqpass")) { /* pass this header without allowing or denying the request */
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_PASS, 0,
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], "reqallow")) { /* allow a request if a header matches this regex */
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_ALLOW, 0,
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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005016 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
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_TARPIT, 0,
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 Tarreaub8750a82006-09-03 09:56:00 +02005022 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005023 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting 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_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005026 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005027 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005028 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005029 }
5030 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005031 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005032 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005033 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005034 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005035 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005038 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5040 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005041 err_code |= ERR_ALERT | ERR_FATAL;
5042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005043 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005044
5045 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005046 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005047 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005048 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 }
5051 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005052 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005053 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005054 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005055 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 }
5058 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005059 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005060 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005061 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005062 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 }
5065 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005066 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005067 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005068 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005069 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 }
5072 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005073 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005074 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005075 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005076 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005078 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005079 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005081 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005082 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005083 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005084 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005086 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005087 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005088
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 if (curproxy == &defproxy) {
5090 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005094 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005095 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097 if (*(args[1]) == 0) {
5098 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005102
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005103 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005104 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5105 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5106 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
5110 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5111 }
5112 else if (*args[2]) {
5113 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5114 file, linenum, args[0], args[2]);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005119 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005120 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005121 wl->s = strdup(args[1]);
5122 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005123 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005124 }
5125 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005126 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005127 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5128 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005131 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005132
Willy Tarreauade5ec42010-01-28 19:33:49 +01005133 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005134 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005135 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005136 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 }
5139 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005141 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005142 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005143 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
5146 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005148 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005149 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005150 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 }
5153 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005154 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005155 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5156 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 }
5160
Willy Tarreauade5ec42010-01-28 19:33:49 +01005161 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005162 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005163 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005164 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
5167 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005169 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005170 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005171 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 }
5174 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005175 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005176 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005177 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
5181 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005182 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005183
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 if (curproxy == &defproxy) {
5185 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005189 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005190 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 if (*(args[1]) == 0) {
5193 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 }
5197
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005198 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005199 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5200 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5201 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
5204 }
5205 err_code |= warnif_cond_requires_req(cond, file, linenum);
5206 }
5207 else if (*args[2]) {
5208 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5209 file, linenum, args[0], args[2]);
5210 err_code |= ERR_ALERT | ERR_FATAL;
5211 goto out;
5212 }
5213
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005214 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005215 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005216 wl->s = strdup(args[1]);
5217 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218 }
5219 else if (!strcmp(args[0], "errorloc") ||
5220 !strcmp(args[0], "errorloc302") ||
5221 !strcmp(args[0], "errorloc303")) { /* error location */
5222 int errnum, errlen;
5223 char *err;
5224
Willy Tarreau977b8e42006-12-29 14:19:17 +01005225 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005226 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005227
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005229 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 }
5233
5234 errnum = atol(args[1]);
5235 if (!strcmp(args[0], "errorloc303")) {
5236 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5237 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5238 } else {
5239 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5240 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5241 }
5242
Willy Tarreau0f772532006-12-23 20:51:41 +01005243 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5244 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005245 chunk_destroy(&curproxy->errmsg[rc]);
5246 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005247 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005250
5251 if (rc >= HTTP_ERR_SIZE) {
5252 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5253 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 free(err);
5255 }
5256 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005257 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5258 int errnum, errlen, fd;
5259 char *err;
5260 struct stat stat;
5261
5262 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005264
5265 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005266 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005267 err_code |= ERR_ALERT | ERR_FATAL;
5268 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005269 }
5270
5271 fd = open(args[2], O_RDONLY);
5272 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5273 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5274 file, linenum, args[2], args[1]);
5275 if (fd >= 0)
5276 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005279 }
5280
Willy Tarreau27a674e2009-08-17 07:23:33 +02005281 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005282 errlen = stat.st_size;
5283 } else {
5284 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005285 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005286 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005287 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005288 }
5289
5290 err = malloc(errlen); /* malloc() must succeed during parsing */
5291 errnum = read(fd, err, errlen);
5292 if (errnum != errlen) {
5293 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5294 file, linenum, args[2], args[1]);
5295 close(fd);
5296 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005299 }
5300 close(fd);
5301
5302 errnum = atol(args[1]);
5303 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5304 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005305 chunk_destroy(&curproxy->errmsg[rc]);
5306 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005307 break;
5308 }
5309 }
5310
5311 if (rc >= HTTP_ERR_SIZE) {
5312 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5313 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005314 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005315 free(err);
5316 }
5317 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005318 else if (!strcmp(args[0], "compression")) {
5319 struct comp *comp;
5320 if (curproxy->comp == NULL) {
5321 comp = calloc(1, sizeof(struct comp));
5322 curproxy->comp = comp;
5323 } else {
5324 comp = curproxy->comp;
5325 }
5326
5327 if (!strcmp(args[1], "algo")) {
5328 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005329 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005330
William Lallemand82fe75c2012-10-23 10:25:10 +02005331 cur_arg = 2;
5332 if (!*args[cur_arg]) {
5333 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5334 file, linenum, args[0]);
5335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
5337 }
5338 while (*(args[cur_arg])) {
5339 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5340 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5341 file, linenum, args[0], args[cur_arg]);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
William Lallemand552df672012-11-07 13:21:47 +01005345 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5346 curproxy->comp->algos->end(&ctx);
5347 } else {
5348 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5349 file, linenum, args[0], args[cur_arg]);
5350 err_code |= ERR_ALERT | ERR_FATAL;
5351 goto out;
5352 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005353 cur_arg ++;
5354 continue;
5355 }
5356 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005357 else if (!strcmp(args[1], "offload")) {
5358 comp->offload = 1;
5359 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005360 else if (!strcmp(args[1], "type")) {
5361 int cur_arg;
5362 cur_arg = 2;
5363 if (!*args[cur_arg]) {
5364 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5365 file, linenum, args[0]);
5366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368 }
5369 while (*(args[cur_arg])) {
5370 comp_append_type(comp, args[cur_arg]);
5371 cur_arg ++;
5372 continue;
5373 }
5374 }
5375 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005376 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005377 file, linenum, args[0]);
5378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
5380 }
5381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005383 struct cfg_kw_list *kwl;
5384 int index;
5385
5386 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5387 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5388 if (kwl->kw[index].section != CFG_LISTEN)
5389 continue;
5390 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5391 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005392 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005393 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005394 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005397 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005398 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005399 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005400 err_code |= ERR_WARN;
5401 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005402 }
Willy Tarreau93893792009-07-23 13:19:11 +02005403 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005404 }
5405 }
5406 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005407
Willy Tarreau6daf3432008-01-22 16:44:08 +01005408 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005411 }
Willy Tarreau93893792009-07-23 13:19:11 +02005412 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005413 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005414 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415}
5416
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005417int
5418cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5419{
5420
5421 int err_code = 0;
5422 const char *err;
5423
5424 if (!strcmp(args[0], "userlist")) { /* new userlist */
5425 struct userlist *newul;
5426
5427 if (!*args[1]) {
5428 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5429 file, linenum, args[0]);
5430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
5432 }
5433
5434 err = invalid_char(args[1]);
5435 if (err) {
5436 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5437 file, linenum, *err, args[0], args[1]);
5438 err_code |= ERR_ALERT | ERR_FATAL;
5439 goto out;
5440 }
5441
5442 for (newul = userlist; newul; newul = newul->next)
5443 if (!strcmp(newul->name, args[1])) {
5444 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5445 file, linenum, args[1]);
5446 err_code |= ERR_WARN;
5447 goto out;
5448 }
5449
5450 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5451 if (!newul) {
5452 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5453 err_code |= ERR_ALERT | ERR_ABORT;
5454 goto out;
5455 }
5456
5457 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5458 newul->name = strdup(args[1]);
5459
5460 if (!newul->groupusers | !newul->name) {
5461 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5462 err_code |= ERR_ALERT | ERR_ABORT;
5463 goto out;
5464 }
5465
5466 newul->next = userlist;
5467 userlist = newul;
5468
5469 } else if (!strcmp(args[0], "group")) { /* new group */
5470 int cur_arg, i;
5471 const char *err;
5472
5473 if (!*args[1]) {
5474 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5475 file, linenum, args[0]);
5476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
5478 }
5479
5480 err = invalid_char(args[1]);
5481 if (err) {
5482 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5483 file, linenum, *err, args[0], args[1]);
5484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
5486 }
5487
5488 for(i = 0; i < userlist->grpcnt; i++)
5489 if (!strcmp(userlist->groups[i], args[1])) {
5490 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5491 file, linenum, args[1], userlist->name);
5492 err_code |= ERR_ALERT;
5493 goto out;
5494 }
5495
5496 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5497 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5498 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5499 err_code |= ERR_ALERT | ERR_FATAL;
5500 goto out;
5501 }
5502
5503 cur_arg = 2;
5504
5505 while (*args[cur_arg]) {
5506 if (!strcmp(args[cur_arg], "users")) {
5507 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5508 cur_arg += 2;
5509 continue;
5510 } else {
5511 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5512 file, linenum, args[0]);
5513 err_code |= ERR_ALERT | ERR_FATAL;
5514 goto out;
5515 }
5516 }
5517
5518 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5519 } else if (!strcmp(args[0], "user")) { /* new user */
5520 struct auth_users *newuser;
5521 int cur_arg;
5522
5523 if (!*args[1]) {
5524 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5525 file, linenum, args[0]);
5526 err_code |= ERR_ALERT | ERR_FATAL;
5527 goto out;
5528 }
5529
5530 for (newuser = userlist->users; newuser; newuser = newuser->next)
5531 if (!strcmp(newuser->user, args[1])) {
5532 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5533 file, linenum, args[1], userlist->name);
5534 err_code |= ERR_ALERT;
5535 goto out;
5536 }
5537
5538 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5539 if (!newuser) {
5540 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5541 err_code |= ERR_ALERT | ERR_ABORT;
5542 goto out;
5543 }
5544
5545 newuser->user = strdup(args[1]);
5546
5547 newuser->next = userlist->users;
5548 userlist->users = newuser;
5549
5550 cur_arg = 2;
5551
5552 while (*args[cur_arg]) {
5553 if (!strcmp(args[cur_arg], "password")) {
5554#ifndef CONFIG_HAP_CRYPT
5555 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5556 file, linenum);
5557 err_code |= ERR_ALERT;
5558#endif
5559 newuser->pass = strdup(args[cur_arg + 1]);
5560 cur_arg += 2;
5561 continue;
5562 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5563 newuser->pass = strdup(args[cur_arg + 1]);
5564 newuser->flags |= AU_O_INSECURE;
5565 cur_arg += 2;
5566 continue;
5567 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005568 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005569 cur_arg += 2;
5570 continue;
5571 } else {
5572 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5573 file, linenum, args[0]);
5574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
5576 }
5577 }
5578 } else {
5579 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5580 err_code |= ERR_ALERT | ERR_FATAL;
5581 }
5582
5583out:
5584 return err_code;
5585}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586
5587/*
5588 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005589 * Returns the error code, 0 if OK, or any combination of :
5590 * - ERR_ABORT: must abort ASAP
5591 * - ERR_FATAL: we can continue parsing but not start the service
5592 * - ERR_WARN: a warning has been emitted
5593 * - ERR_ALERT: an alert has been emitted
5594 * Only the two first ones can stop processing, the two others are just
5595 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005597int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005599 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600 FILE *f;
5601 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005603 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 if ((f=fopen(file,"r")) == NULL)
5606 return -1;
5607
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005608 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005609 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005610 char *end;
5611 char *args[MAX_LINE_ARGS + 1];
5612 char *line = thisline;
5613
Willy Tarreaubaaee002006-06-26 02:48:02 +02005614 linenum++;
5615
5616 end = line + strlen(line);
5617
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005618 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5619 /* Check if we reached the limit and the last char is not \n.
5620 * Watch out for the last line without the terminating '\n'!
5621 */
5622 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005623 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005624 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005625 }
5626
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005628 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005629 line++;
5630
5631 arg = 0;
5632 args[arg] = line;
5633
5634 while (*line && arg < MAX_LINE_ARGS) {
5635 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5636 * C equivalent value. Other combinations left unchanged (eg: \1).
5637 */
5638 if (*line == '\\') {
5639 int skip = 0;
5640 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5641 *line = line[1];
5642 skip = 1;
5643 }
5644 else if (line[1] == 'r') {
5645 *line = '\r';
5646 skip = 1;
5647 }
5648 else if (line[1] == 'n') {
5649 *line = '\n';
5650 skip = 1;
5651 }
5652 else if (line[1] == 't') {
5653 *line = '\t';
5654 skip = 1;
5655 }
5656 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005657 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 unsigned char hex1, hex2;
5659 hex1 = toupper(line[2]) - '0';
5660 hex2 = toupper(line[3]) - '0';
5661 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5662 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5663 *line = (hex1<<4) + hex2;
5664 skip = 3;
5665 }
5666 else {
5667 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005668 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 }
5670 }
5671 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005672 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 end -= skip;
5674 }
5675 line++;
5676 }
5677 else if (*line == '#' || *line == '\n' || *line == '\r') {
5678 /* end of string, end of loop */
5679 *line = 0;
5680 break;
5681 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005682 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005683 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005684 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005685 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 line++;
5687 args[++arg] = line;
5688 }
5689 else {
5690 line++;
5691 }
5692 }
5693
5694 /* empty line */
5695 if (!**args)
5696 continue;
5697
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005698 if (*line) {
5699 /* we had to stop due to too many args.
5700 * Let's terminate the string, print the offending part then cut the
5701 * last arg.
5702 */
5703 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5704 line++;
5705 *line = '\0';
5706
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005707 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005708 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005709 err_code |= ERR_ALERT | ERR_FATAL;
5710 args[arg] = line;
5711 }
5712
Willy Tarreau540abe42007-05-02 20:50:16 +02005713 /* zero out remaining args and ensure that at least one entry
5714 * is zeroed out.
5715 */
5716 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 args[arg] = line;
5718 }
5719
Willy Tarreau3842f002009-06-14 11:39:52 +02005720 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005721 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005722 char *tmp;
5723
Willy Tarreau3842f002009-06-14 11:39:52 +02005724 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005725 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005726 for (arg=0; *args[arg+1]; arg++)
5727 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005728 *tmp = '\0'; // fix the next arg to \0
5729 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005730 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005731 else if (!strcmp(args[0], "default")) {
5732 kwm = KWM_DEF;
5733 for (arg=0; *args[arg+1]; arg++)
5734 args[arg] = args[arg+1]; // shift args after inversion
5735 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005736
William Lallemand0f99e342011-10-12 17:50:54 +02005737 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5738 strcmp(args[0], "log") != 0) {
5739 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005740 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005741 }
5742
Willy Tarreau977b8e42006-12-29 14:19:17 +01005743 if (!strcmp(args[0], "listen") ||
5744 !strcmp(args[0], "frontend") ||
5745 !strcmp(args[0], "backend") ||
5746 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005747 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005749 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005750 cursection = strdup(args[0]);
5751 }
5752 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005754 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005755 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005756 }
5757 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005758 confsect = CFG_USERLIST;
5759 free(cursection);
5760 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005761 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005762 else if (!strcmp(args[0], "peers")) {
5763 confsect = CFG_PEERS;
5764 free(cursection);
5765 cursection = strdup(args[0]);
5766 }
5767
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 /* else it's a section keyword */
5769
5770 switch (confsect) {
5771 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005772 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773 break;
5774 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005775 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005776 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005777 case CFG_USERLIST:
5778 err_code |= cfg_parse_users(file, linenum, args, kwm);
5779 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005780 case CFG_PEERS:
5781 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5782 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005783 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005784 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005785 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005787
5788 if (err_code & ERR_ABORT)
5789 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005790 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005791 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005792 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005794 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005795}
5796
Willy Tarreaubb925012009-07-23 13:36:36 +02005797/*
5798 * Returns the error code, 0 if OK, or any combination of :
5799 * - ERR_ABORT: must abort ASAP
5800 * - ERR_FATAL: we can continue parsing but not start the service
5801 * - ERR_WARN: a warning has been emitted
5802 * - ERR_ALERT: an alert has been emitted
5803 * Only the two first ones can stop processing, the two others are just
5804 * indicators.
5805 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005806int check_config_validity()
5807{
5808 int cfgerr = 0;
5809 struct proxy *curproxy = NULL;
5810 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005811 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005812 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005813 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005814 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005815
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005816 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 /*
5818 * Now, check for the integrity of all that we have collected.
5819 */
5820
5821 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005822 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005823
Willy Tarreau193b8c62012-11-22 00:17:38 +01005824 if (!global.tune.max_http_hdr)
5825 global.tune.max_http_hdr = MAX_HTTP_HDR;
5826
5827 if (!global.tune.cookie_len)
5828 global.tune.cookie_len = CAPTURE_LEN;
5829
5830 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5831
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005832 /* first, we will invert the proxy list order */
5833 curproxy = NULL;
5834 while (proxy) {
5835 struct proxy *next;
5836
5837 next = proxy->next;
5838 proxy->next = curproxy;
5839 curproxy = proxy;
5840 if (!next)
5841 break;
5842 proxy = next;
5843 }
5844
Willy Tarreaubaaee002006-06-26 02:48:02 +02005845 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005846 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005847 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005848 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005849 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005850 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005851 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005852 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005853
Willy Tarreau050536d2012-10-04 08:47:34 +02005854 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005855 /* proxy ID not set, use automatic numbering with first
5856 * spare entry starting with next_pxid.
5857 */
5858 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5859 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5860 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005861 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005862 next_pxid++;
5863
Willy Tarreau55ea7572007-06-17 19:56:27 +02005864
Willy Tarreaubaaee002006-06-26 02:48:02 +02005865 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005866 /* ensure we don't keep listeners uselessly bound */
5867 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005868 curproxy = curproxy->next;
5869 continue;
5870 }
5871
Willy Tarreau16a21472012-11-19 12:39:59 +01005872 /* number of processes this proxy is bound to */
5873 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5874
Willy Tarreauff01a212009-03-15 13:46:16 +01005875 switch (curproxy->mode) {
5876 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005877 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005878 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005879 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5880 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005881 cfgerr++;
5882 }
5883
5884 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005885 Warning("config : servers will be ignored for %s '%s'.\n",
5886 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005887 break;
5888
5889 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005890 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005891 break;
5892
5893 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005894 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005895 break;
5896 }
5897
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005898 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005899 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005900 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005901 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5902 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005903 cfgerr++;
5904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005906 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005907 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5908 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005909 cfgerr++;
5910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005911#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005912 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005913 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5914 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005915 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005916 }
5917 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005918 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005919 /* If no LB algo is set in a backend, and we're not in
5920 * transparent mode, dispatch mode nor proxy mode, we
5921 * want to use balance roundrobin by default.
5922 */
5923 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5924 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005925 }
5926 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005927
Willy Tarreau1620ec32011-08-06 17:05:02 +02005928 if (curproxy->options & PR_O_DISPATCH)
5929 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5930 else if (curproxy->options & PR_O_HTTP_PROXY)
5931 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5932 else if (curproxy->options & PR_O_TRANSP)
5933 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005934
Willy Tarreau1620ec32011-08-06 17:05:02 +02005935 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5936 if (curproxy->options & PR_O_DISABLE404) {
5937 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5938 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5939 err_code |= ERR_WARN;
5940 curproxy->options &= ~PR_O_DISABLE404;
5941 }
5942 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5943 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5944 "send-state", proxy_type_str(curproxy), curproxy->id);
5945 err_code |= ERR_WARN;
5946 curproxy->options &= ~PR_O2_CHK_SNDST;
5947 }
Willy Tarreauef781042010-01-27 11:53:01 +01005948 }
5949
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005950 /* if a default backend was specified, let's find it */
5951 if (curproxy->defbe.name) {
5952 struct proxy *target;
5953
Alex Williams96532db2009-11-01 21:27:13 -05005954 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005955 if (!target) {
5956 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5957 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005958 cfgerr++;
5959 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005960 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5961 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005962 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005963 } else {
5964 free(curproxy->defbe.name);
5965 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005966 /* we force the backend to be present on at least all of
5967 * the frontend's processes.
5968 */
5969 target->bind_proc = curproxy->bind_proc ?
5970 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005971
5972 /* Emit a warning if this proxy also has some servers */
5973 if (curproxy->srv) {
5974 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5975 curproxy->id);
5976 err_code |= ERR_WARN;
5977 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005978 }
5979 }
5980
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005981 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005982 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5983 /* map jump target for ACT_SETBE in req_rep chain */
5984 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005985 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005986 struct proxy *target;
5987
Willy Tarreaua496b602006-12-17 23:15:24 +01005988 if (exp->action != ACT_SETBE)
5989 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005990
Alex Williams96532db2009-11-01 21:27:13 -05005991 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005992 if (!target) {
5993 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5994 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005995 cfgerr++;
5996 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005997 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5998 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005999 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006000 } else {
6001 free((void *)exp->replace);
6002 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006003 /* we force the backend to be present on at least all of
6004 * the frontend's processes.
6005 */
6006 target->bind_proc = curproxy->bind_proc ?
6007 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006008 }
6009 }
6010 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006011
6012 /* find the target proxy for 'use_backend' rules */
6013 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006014 struct proxy *target;
6015
Alex Williams96532db2009-11-01 21:27:13 -05006016 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006017
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006018 if (!target) {
6019 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6020 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006021 cfgerr++;
6022 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006023 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6024 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006025 cfgerr++;
6026 } else {
6027 free((void *)rule->be.name);
6028 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006029 /* we force the backend to be present on at least all of
6030 * the frontend's processes.
6031 */
6032 target->bind_proc = curproxy->bind_proc ?
6033 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006034 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006035 }
6036
6037 /* find the target proxy for 'use_backend' rules */
6038 list_for_each_entry(srule, &curproxy->server_rules, list) {
6039 struct server *target = findserver(curproxy, srule->srv.name);
6040
6041 if (!target) {
6042 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6043 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6044 cfgerr++;
6045 continue;
6046 }
6047 free((void *)srule->srv.name);
6048 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006049 }
6050
Emeric Brunb982a3d2010-01-04 15:45:53 +01006051 /* find the target table for 'stick' rules */
6052 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6053 struct proxy *target;
6054
Emeric Brun1d33b292010-01-04 15:47:17 +01006055 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6056 if (mrule->flags & STK_IS_STORE)
6057 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6058
Emeric Brunb982a3d2010-01-04 15:45:53 +01006059 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006060 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006061 else
6062 target = curproxy;
6063
6064 if (!target) {
6065 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6066 curproxy->id, mrule->table.name);
6067 cfgerr++;
6068 }
6069 else if (target->table.size == 0) {
6070 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6071 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6072 cfgerr++;
6073 }
Willy Tarreau12785782012-04-27 21:37:17 +02006074 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6075 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006076 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6077 cfgerr++;
6078 }
6079 else {
6080 free((void *)mrule->table.name);
6081 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006082 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006083 }
6084 }
6085
6086 /* find the target table for 'store response' rules */
6087 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6088 struct proxy *target;
6089
Emeric Brun1d33b292010-01-04 15:47:17 +01006090 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6091
Emeric Brunb982a3d2010-01-04 15:45:53 +01006092 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006093 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006094 else
6095 target = curproxy;
6096
6097 if (!target) {
6098 Alert("Proxy '%s': unable to find store table '%s'.\n",
6099 curproxy->id, mrule->table.name);
6100 cfgerr++;
6101 }
6102 else if (target->table.size == 0) {
6103 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6104 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6105 cfgerr++;
6106 }
Willy Tarreau12785782012-04-27 21:37:17 +02006107 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6108 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006109 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6110 cfgerr++;
6111 }
6112 else {
6113 free((void *)mrule->table.name);
6114 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006115 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006116 }
6117 }
6118
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006119 /* find the target table for 'tcp-request' layer 4 rules */
6120 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6121 struct proxy *target;
6122
Willy Tarreau56123282010-08-06 19:06:56 +02006123 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006124 continue;
6125
6126 if (trule->act_prm.trk_ctr.table.n)
6127 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6128 else
6129 target = curproxy;
6130
6131 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006132 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6133 curproxy->id, trule->act_prm.trk_ctr.table.n,
6134 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006135 cfgerr++;
6136 }
6137 else if (target->table.size == 0) {
6138 Alert("Proxy '%s': table '%s' used but not configured.\n",
6139 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6140 cfgerr++;
6141 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006142 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6143 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6144 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6145 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6146 cfgerr++;
6147 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006148 else {
6149 free(trule->act_prm.trk_ctr.table.n);
6150 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006151 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006152 * to pass a list of counters to track and allocate them right here using
6153 * stktable_alloc_data_type().
6154 */
6155 }
6156 }
6157
Willy Tarreaud1f96522010-08-03 19:34:32 +02006158 /* find the target table for 'tcp-request' layer 6 rules */
6159 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6160 struct proxy *target;
6161
Willy Tarreau56123282010-08-06 19:06:56 +02006162 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006163 continue;
6164
6165 if (trule->act_prm.trk_ctr.table.n)
6166 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6167 else
6168 target = curproxy;
6169
6170 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006171 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6172 curproxy->id, trule->act_prm.trk_ctr.table.n,
6173 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006174 cfgerr++;
6175 }
6176 else if (target->table.size == 0) {
6177 Alert("Proxy '%s': table '%s' used but not configured.\n",
6178 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6179 cfgerr++;
6180 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006181 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6182 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6183 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6184 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6185 cfgerr++;
6186 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006187 else {
6188 free(trule->act_prm.trk_ctr.table.n);
6189 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006190 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006191 * to pass a list of counters to track and allocate them right here using
6192 * stktable_alloc_data_type().
6193 */
6194 }
6195 }
6196
Emeric Brun32da3c42010-09-23 18:39:19 +02006197 if (curproxy->table.peers.name) {
6198 struct peers *curpeers = peers;
6199
6200 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6201 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6202 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006203 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006204 break;
6205 }
6206 }
6207
6208 if (!curpeers) {
6209 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6210 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006211 free((void *)curproxy->table.peers.name);
6212 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006213 cfgerr++;
6214 }
6215 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006216 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6217 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006218 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006219 cfgerr++;
6220 }
6221 }
6222
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006223 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006224 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006225 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6226 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6227 "proxy", curproxy->id);
6228 cfgerr++;
6229 goto out_uri_auth_compat;
6230 }
6231
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006232 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006233 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006234 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006235 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006236
Willy Tarreau95fa4692010-02-01 13:05:50 +01006237 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6238 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006239
6240 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006241 uri_auth_compat_req[i++] = "realm";
6242 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6243 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006244
Willy Tarreau95fa4692010-02-01 13:05:50 +01006245 uri_auth_compat_req[i++] = "unless";
6246 uri_auth_compat_req[i++] = "{";
6247 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6248 uri_auth_compat_req[i++] = "}";
6249 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006250
Willy Tarreauff011f22011-01-06 17:51:27 +01006251 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6252 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006253 cfgerr++;
6254 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006255 }
6256
Willy Tarreauff011f22011-01-06 17:51:27 +01006257 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006258
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006259 if (curproxy->uri_auth->auth_realm) {
6260 free(curproxy->uri_auth->auth_realm);
6261 curproxy->uri_auth->auth_realm = NULL;
6262 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006263
6264 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006265 }
6266out_uri_auth_compat:
6267
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006268 cfgerr += acl_find_targets(curproxy);
6269
Willy Tarreau2738a142006-07-08 17:28:09 +02006270 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006271 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006272 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006273 (!curproxy->timeout.connect ||
6274 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006275 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006276 " | While not properly invalid, you will certainly encounter various problems\n"
6277 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006278 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006279 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006280 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006281 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006282
Willy Tarreau1fa31262007-12-03 00:36:16 +01006283 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6284 * We must still support older configurations, so let's find out whether those
6285 * parameters have been set or must be copied from contimeouts.
6286 */
6287 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006288 if (!curproxy->timeout.tarpit ||
6289 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006290 /* tarpit timeout not set. We search in the following order:
6291 * default.tarpit, curr.connect, default.connect.
6292 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006293 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006294 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006295 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006296 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006297 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006298 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006299 }
6300 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006301 (!curproxy->timeout.queue ||
6302 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006303 /* queue timeout not set. We search in the following order:
6304 * default.queue, curr.connect, default.connect.
6305 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006306 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006307 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006308 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006309 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006310 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006311 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006312 }
6313 }
6314
Willy Tarreau1620ec32011-08-06 17:05:02 +02006315 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006316 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6317 curproxy->check_req = (char *)malloc(curproxy->check_len);
6318 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006319 }
6320
Willy Tarreau193b8c62012-11-22 00:17:38 +01006321 /* ensure that cookie capture length is not too large */
6322 if (curproxy->capture_len >= global.tune.cookie_len) {
6323 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6324 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6325 err_code |= ERR_WARN;
6326 curproxy->capture_len = global.tune.cookie_len - 1;
6327 }
6328
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006329 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006330 if (curproxy->nb_req_cap) {
6331 if (curproxy->mode == PR_MODE_HTTP) {
6332 curproxy->req_cap_pool = create_pool("ptrcap",
6333 curproxy->nb_req_cap * sizeof(char *),
6334 MEM_F_SHARED);
6335 } else {
6336 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6337 proxy_type_str(curproxy), curproxy->id);
6338 err_code |= ERR_WARN;
6339 curproxy->to_log &= ~LW_REQHDR;
6340 curproxy->nb_req_cap = 0;
6341 }
6342 }
6343
6344 if (curproxy->nb_rsp_cap) {
6345 if (curproxy->mode == PR_MODE_HTTP) {
6346 curproxy->rsp_cap_pool = create_pool("ptrcap",
6347 curproxy->nb_rsp_cap * sizeof(char *),
6348 MEM_F_SHARED);
6349 } else {
6350 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6351 proxy_type_str(curproxy), curproxy->id);
6352 err_code |= ERR_WARN;
6353 curproxy->to_log &= ~LW_REQHDR;
6354 curproxy->nb_rsp_cap = 0;
6355 }
6356 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006357
Willy Tarreau196729e2012-05-31 19:30:26 +02006358 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006359 if (!(curproxy->cap & PR_CAP_FE)) {
6360 if (curproxy->logformat_string != default_http_log_format &&
6361 curproxy->logformat_string != default_tcp_log_format &&
6362 curproxy->logformat_string != clf_http_log_format)
6363 free(curproxy->logformat_string);
6364 curproxy->logformat_string = NULL;
6365 }
6366
Willy Tarreau196729e2012-05-31 19:30:26 +02006367 if (curproxy->logformat_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006368 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY);
Willy Tarreau196729e2012-05-31 19:30:26 +02006369
6370 if (curproxy->uniqueid_format_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006371 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0);
Willy Tarreau196729e2012-05-31 19:30:26 +02006372
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373 /* first, we will invert the servers list order */
6374 newsrv = NULL;
6375 while (curproxy->srv) {
6376 struct server *next;
6377
6378 next = curproxy->srv->next;
6379 curproxy->srv->next = newsrv;
6380 newsrv = curproxy->srv;
6381 if (!next)
6382 break;
6383 curproxy->srv = next;
6384 }
6385
Willy Tarreaudd701652010-05-25 23:03:02 +02006386 /* assign automatic UIDs to servers which don't have one yet */
6387 next_id = 1;
6388 newsrv = curproxy->srv;
6389 while (newsrv != NULL) {
6390 if (!newsrv->puid) {
6391 /* server ID not set, use automatic numbering with first
6392 * spare entry starting with next_svid.
6393 */
6394 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6395 newsrv->conf.id.key = newsrv->puid = next_id;
6396 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6397 }
6398 next_id++;
6399 newsrv = newsrv->next;
6400 }
6401
Willy Tarreau20697042007-11-15 23:26:18 +01006402 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006403 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006404
Willy Tarreau62c3be22012-01-20 13:12:32 +01006405 /*
6406 * If this server supports a maxconn parameter, it needs a dedicated
6407 * tasks to fill the emptied slots when a connection leaves.
6408 * Also, resolve deferred tracking dependency if needed.
6409 */
6410 newsrv = curproxy->srv;
6411 while (newsrv != NULL) {
6412 if (newsrv->minconn > newsrv->maxconn) {
6413 /* Only 'minconn' was specified, or it was higher than or equal
6414 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6415 * this will avoid further useless expensive computations.
6416 */
6417 newsrv->maxconn = newsrv->minconn;
6418 } else if (newsrv->maxconn && !newsrv->minconn) {
6419 /* minconn was not specified, so we set it to maxconn */
6420 newsrv->minconn = newsrv->maxconn;
6421 }
6422
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006423#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006424 if (newsrv->use_ssl || newsrv->check.use_ssl)
6425 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006426#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006427
Willy Tarreau62c3be22012-01-20 13:12:32 +01006428 if (newsrv->trackit) {
6429 struct proxy *px;
6430 struct server *srv;
6431 char *pname, *sname;
6432
6433 pname = newsrv->trackit;
6434 sname = strrchr(pname, '/');
6435
6436 if (sname)
6437 *sname++ = '\0';
6438 else {
6439 sname = pname;
6440 pname = NULL;
6441 }
6442
6443 if (pname) {
6444 px = findproxy(pname, PR_CAP_BE);
6445 if (!px) {
6446 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6447 proxy_type_str(curproxy), curproxy->id,
6448 newsrv->id, pname);
6449 cfgerr++;
6450 goto next_srv;
6451 }
6452 } else
6453 px = curproxy;
6454
6455 srv = findserver(px, sname);
6456 if (!srv) {
6457 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6458 proxy_type_str(curproxy), curproxy->id,
6459 newsrv->id, sname);
6460 cfgerr++;
6461 goto next_srv;
6462 }
6463
6464 if (!(srv->state & SRV_CHECKED)) {
6465 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6466 "tracking as it does not have checks enabled.\n",
6467 proxy_type_str(curproxy), curproxy->id,
6468 newsrv->id, px->id, srv->id);
6469 cfgerr++;
6470 goto next_srv;
6471 }
6472
6473 if (curproxy != px &&
6474 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6475 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6476 "tracking: disable-on-404 option inconsistency.\n",
6477 proxy_type_str(curproxy), curproxy->id,
6478 newsrv->id, px->id, srv->id);
6479 cfgerr++;
6480 goto next_srv;
6481 }
6482
6483 /* if the other server is forced disabled, we have to do the same here */
6484 if (srv->state & SRV_MAINTAIN) {
6485 newsrv->state |= SRV_MAINTAIN;
6486 newsrv->state &= ~SRV_RUNNING;
6487 newsrv->health = 0;
6488 }
6489
6490 newsrv->track = srv;
6491 newsrv->tracknext = srv->tracknext;
6492 srv->tracknext = newsrv;
6493
6494 free(newsrv->trackit);
6495 newsrv->trackit = NULL;
6496 }
6497 next_srv:
6498 newsrv = newsrv->next;
6499 }
6500
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006501 /* We have to initialize the server lookup mechanism depending
6502 * on what LB algorithm was choosen.
6503 */
6504
6505 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6506 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6507 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006508 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6509 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6510 init_server_map(curproxy);
6511 } else {
6512 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6513 fwrr_init_server_groups(curproxy);
6514 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006515 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006516
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006517 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006518 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6519 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6520 fwlc_init_server_tree(curproxy);
6521 } else {
6522 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6523 fas_init_server_tree(curproxy);
6524 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006525 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006526
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006527 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006528 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6529 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6530 chash_init_server_tree(curproxy);
6531 } else {
6532 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6533 init_server_map(curproxy);
6534 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006535 break;
6536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537
6538 if (curproxy->options & PR_O_LOGASAP)
6539 curproxy->to_log &= ~LW_BYTES;
6540
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006541 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006542 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006543 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6544 proxy_type_str(curproxy), curproxy->id);
6545 err_code |= ERR_WARN;
6546 }
6547
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006548 if (curproxy->mode != PR_MODE_HTTP) {
6549 int optnum;
6550
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006551 if (curproxy->uri_auth) {
6552 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6553 proxy_type_str(curproxy), curproxy->id);
6554 err_code |= ERR_WARN;
6555 curproxy->uri_auth = NULL;
6556 }
6557
Willy Tarreau87cf5142011-08-19 22:57:24 +02006558 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006559 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6560 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6561 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006562 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006563 }
6564
6565 if (curproxy->options & PR_O_ORGTO) {
6566 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6567 "originalto", proxy_type_str(curproxy), curproxy->id);
6568 err_code |= ERR_WARN;
6569 curproxy->options &= ~PR_O_ORGTO;
6570 }
6571
6572 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6573 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6574 (curproxy->cap & cfg_opts[optnum].cap) &&
6575 (curproxy->options & cfg_opts[optnum].val)) {
6576 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6577 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6578 err_code |= ERR_WARN;
6579 curproxy->options &= ~cfg_opts[optnum].val;
6580 }
6581 }
6582
6583 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6584 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6585 (curproxy->cap & cfg_opts2[optnum].cap) &&
6586 (curproxy->options2 & cfg_opts2[optnum].val)) {
6587 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6588 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6589 err_code |= ERR_WARN;
6590 curproxy->options2 &= ~cfg_opts2[optnum].val;
6591 }
6592 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006593
Willy Tarreauefa5f512010-03-30 20:13:29 +02006594#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006595 if (curproxy->conn_src.bind_hdr_occ) {
6596 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006597 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006598 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006599 err_code |= ERR_WARN;
6600 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006601#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006602 }
6603
Willy Tarreaubaaee002006-06-26 02:48:02 +02006604 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006605 * ensure that we're not cross-dressing a TCP server into HTTP.
6606 */
6607 newsrv = curproxy->srv;
6608 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006609 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006610 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6611 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006612 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006613 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006614
Willy Tarreau0cec3312011-10-31 13:49:26 +01006615 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6616 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6617 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6618 err_code |= ERR_WARN;
6619 }
6620
Willy Tarreauefa5f512010-03-30 20:13:29 +02006621#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006622 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6623 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006624 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006625 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006626 err_code |= ERR_WARN;
6627 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006628#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006629 newsrv = newsrv->next;
6630 }
6631
Willy Tarreauc1a21672009-08-16 22:37:44 +02006632 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006633 if (!curproxy->accept)
6634 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006635
Willy Tarreauc1a21672009-08-16 22:37:44 +02006636 if (curproxy->tcp_req.inspect_delay ||
6637 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006638 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006639
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006640 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006641 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006642 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006643 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006644
6645 /* both TCP and HTTP must check switching rules */
6646 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6647 }
6648
6649 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006650 if (curproxy->tcp_req.inspect_delay ||
6651 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6652 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6653
Emeric Brun97679e72010-09-23 17:56:44 +02006654 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6655 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6656
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006657 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006658 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006659 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006660 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006661
6662 /* If the backend does requires RDP cookie persistence, we have to
6663 * enable the corresponding analyser.
6664 */
6665 if (curproxy->options2 & PR_O2_RDPC_PRST)
6666 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6667 }
6668
Emeric Brunc52962f2012-11-15 18:28:02 +01006669#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006670 /* Configure SSL for each bind line.
6671 * Note: if configuration fails at some point, the ->ctx member
6672 * remains NULL so that listeners can later detach.
6673 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006674 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006675 if (!bind_conf->is_ssl) {
6676 if (bind_conf->default_ctx) {
6677 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6678 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6679 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006680 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006681 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006682 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006683 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006684 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006685 cfgerr++;
6686 continue;
6687 }
6688
Emeric Brun4b3091e2012-09-24 15:48:52 +02006689 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006690 Alert("Unable to allocate SSL session cache.\n");
6691 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006692 continue;
6693 }
6694
Emeric Brunfc0421f2012-09-07 17:30:07 +02006695 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006696 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006697 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006698#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006699
Willy Tarreaue6b98942007-10-29 01:09:36 +01006700 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006701 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006702 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006703 if (!listener->luid) {
6704 /* listener ID not set, use automatic numbering with first
6705 * spare entry starting with next_luid.
6706 */
6707 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6708 listener->conf.id.key = listener->luid = next_id;
6709 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006710 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006711 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006712
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006713 /* enable separate counters */
6714 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6715 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006716 if (!listener->name)
6717 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006718 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006719
Willy Tarreaue6b98942007-10-29 01:09:36 +01006720 if (curproxy->options & PR_O_TCP_NOLING)
6721 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006722 if (!listener->maxconn)
6723 listener->maxconn = curproxy->maxconn;
6724 if (!listener->backlog)
6725 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006726 if (!listener->maxaccept)
6727 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6728
6729 /* we want to have an optimal behaviour on single process mode to
6730 * maximize the work at once, but in multi-process we want to keep
6731 * some fairness between processes, so we target half of the max
6732 * number of events to be balanced over all the processes the proxy
6733 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6734 * used to disable the limit.
6735 */
6736 if (listener->maxaccept > 0) {
6737 if (nbproc > 1)
6738 listener->maxaccept = (listener->maxaccept + 1) / 2;
6739 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6740 }
6741
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006742 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006743 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006744 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006745 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006746
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006747 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6748 listener->options |= LI_O_TCP_RULES;
6749
Willy Tarreaude3041d2010-05-31 10:56:17 +02006750 if (curproxy->mon_mask.s_addr)
6751 listener->options |= LI_O_CHK_MONNET;
6752
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006753 /* smart accept mode is automatic in HTTP mode */
6754 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006755 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006756 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6757 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006758 }
6759
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006760 /* Release unused SSL configs */
6761 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6762 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006763 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006764#ifdef USE_OPENSSL
6765 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006766 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006767 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006768 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006769 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006770#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006771 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006772
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006773 /* Check multi-process mode compatibility for the current proxy */
6774 if (global.nbproc > 1) {
6775 int nbproc = 0;
6776 if (curproxy->bind_proc) {
6777 int proc;
6778 for (proc = 0; proc < global.nbproc; proc++) {
6779 if (curproxy->bind_proc & (1 << proc)) {
6780 nbproc++;
6781 }
6782 }
6783 } else {
6784 nbproc = global.nbproc;
6785 }
6786 if (curproxy->table.peers.name) {
6787 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6788 curproxy->id);
6789 cfgerr++;
6790 }
6791 if (nbproc > 1) {
6792 if (curproxy->uri_auth) {
6793 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6794 curproxy->id);
6795 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6796 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6797 curproxy->id);
6798 }
6799 }
6800 if (curproxy->appsession_name) {
6801 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6802 curproxy->id);
6803 }
6804 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6805 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6806 curproxy->id);
6807 }
6808 }
6809 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006810
6811 /* create the task associated with the proxy */
6812 curproxy->task = task_new();
6813 if (curproxy->task) {
6814 curproxy->task->context = curproxy;
6815 curproxy->task->process = manage_proxy;
6816 /* no need to queue, it will be done automatically if some
6817 * listener gets limited.
6818 */
6819 curproxy->task->expire = TICK_ETERNITY;
6820 } else {
6821 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6822 curproxy->id);
6823 cfgerr++;
6824 }
6825
Willy Tarreaubaaee002006-06-26 02:48:02 +02006826 curproxy = curproxy->next;
6827 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006828
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006829 /* Check multi-process mode compatibility */
6830 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006831 if (global.stats_fe && !global.stats_fe->bind_proc) {
6832 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding using 'stats bind-process'.\n");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006833 }
6834 }
6835
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006836 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6837 struct auth_users *curuser;
6838 int g;
6839
6840 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6841 unsigned int group_mask = 0;
6842 char *group = NULL;
6843
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006844 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006845 continue;
6846
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006847 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006848
6849 for (g = 0; g < curuserlist->grpcnt; g++)
6850 if (!strcmp(curuserlist->groups[g], group))
6851 break;
6852
6853 if (g == curuserlist->grpcnt) {
6854 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6855 curuserlist->name, group, curuser->user);
6856 err_code |= ERR_ALERT | ERR_FATAL;
6857 goto out;
6858 }
6859
6860 group_mask |= (1 << g);
6861 }
6862
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006863 free(curuser->u.groups);
6864 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006865 }
6866
6867 for (g = 0; g < curuserlist->grpcnt; g++) {
6868 char *user = NULL;
6869
6870 if (!curuserlist->groupusers[g])
6871 continue;
6872
6873 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6874 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6875 if (!strcmp(curuser->user, user))
6876 break;
6877
6878 if (!curuser) {
6879 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6880 curuserlist->name, user, curuserlist->groups[g]);
6881 err_code |= ERR_ALERT | ERR_FATAL;
6882 goto out;
6883 }
6884
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006885 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006886 }
6887
6888 free(curuserlist->groupusers[g]);
6889 }
6890
6891 free(curuserlist->groupusers);
6892
6893#ifdef DEBUG_AUTH
6894 for (g = 0; g < curuserlist->grpcnt; g++) {
6895 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6896
6897 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006898 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006899 fprintf(stderr, " %s", curuser->user);
6900 }
6901
6902 fprintf(stderr, "\n");
6903 }
6904#endif
6905
Willy Tarreaufbb78422011-06-05 15:38:35 +02006906 }
6907
6908 /* automatically compute fullconn if not set. We must not do it in the
6909 * loop above because cross-references are not yet fully resolved.
6910 */
6911 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6912 /* If <fullconn> is not set, let's set it to 10% of the sum of
6913 * the possible incoming frontend's maxconns.
6914 */
6915 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6916 struct proxy *fe;
6917 int total = 0;
6918
6919 /* sum up the number of maxconns of frontends which
6920 * reference this backend at least once or which are
6921 * the same one ('listen').
6922 */
6923 for (fe = proxy; fe; fe = fe->next) {
6924 struct switching_rule *rule;
6925 struct hdr_exp *exp;
6926 int found = 0;
6927
6928 if (!(fe->cap & PR_CAP_FE))
6929 continue;
6930
6931 if (fe == curproxy) /* we're on a "listen" instance */
6932 found = 1;
6933
6934 if (fe->defbe.be == curproxy) /* "default_backend" */
6935 found = 1;
6936
6937 /* check if a "use_backend" rule matches */
6938 if (!found) {
6939 list_for_each_entry(rule, &fe->switching_rules, list) {
6940 if (rule->be.backend == curproxy) {
6941 found = 1;
6942 break;
6943 }
6944 }
6945 }
6946
6947 /* check if a "reqsetbe" rule matches */
6948 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6949 if (exp->action == ACT_SETBE &&
6950 (struct proxy *)exp->replace == curproxy) {
6951 found = 1;
6952 break;
6953 }
6954 }
6955
6956 /* now we've checked all possible ways to reference a backend
6957 * from a frontend.
6958 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006959 if (!found)
6960 continue;
6961 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006962 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006963 /* we have the sum of the maxconns in <total>. We only
6964 * keep 10% of that sum to set the default fullconn, with
6965 * a hard minimum of 1 (to avoid a divide by zero).
6966 */
6967 curproxy->fullconn = (total + 9) / 10;
6968 if (!curproxy->fullconn)
6969 curproxy->fullconn = 1;
6970 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006971 }
6972
Willy Tarreau056f5682010-06-06 15:51:11 +02006973 /* initialize stick-tables on backend capable proxies. This must not
6974 * be done earlier because the data size may be discovered while parsing
6975 * other proxies.
6976 */
6977 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006978 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006979
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006980 /*
6981 * Recount currently required checks.
6982 */
6983
6984 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6985 int optnum;
6986
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006987 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6988 if (curproxy->options & cfg_opts[optnum].val)
6989 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006990
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006991 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6992 if (curproxy->options2 & cfg_opts2[optnum].val)
6993 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006994 }
6995
Willy Tarreau122541c2011-09-07 21:24:49 +02006996 if (peers) {
6997 struct peers *curpeers = peers, **last;
6998 struct peer *p, *pb;
6999
7000 /* Remove all peers sections which don't have a valid listener.
7001 * This can happen when a peers section is never referenced and
7002 * does not contain a local peer.
7003 */
7004 last = &peers;
7005 while (*last) {
7006 curpeers = *last;
7007 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007008 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007009 last = &curpeers->next;
7010 continue;
7011 }
7012
7013 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7014 curpeers->id, localpeer);
7015
7016 p = curpeers->remote;
7017 while (p) {
7018 pb = p->next;
7019 free(p->id);
7020 free(p);
7021 p = pb;
7022 }
7023
7024 /* Destroy and unlink this curpeers section.
7025 * Note: curpeers is backed up into *last.
7026 */
7027 free(curpeers->id);
7028 curpeers = curpeers->next;
7029 free(*last);
7030 *last = curpeers;
7031 }
7032 }
7033
Willy Tarreau34eb6712011-10-24 18:15:04 +02007034 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007035 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007036 MEM_F_SHARED);
7037
Willy Tarreaubb925012009-07-23 13:36:36 +02007038 if (cfgerr > 0)
7039 err_code |= ERR_ALERT | ERR_FATAL;
7040 out:
7041 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007042}
7043
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007044/*
7045 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7046 * parsing sessions.
7047 */
7048void cfg_register_keywords(struct cfg_kw_list *kwl)
7049{
7050 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7051}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007052
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007053/*
7054 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7055 */
7056void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7057{
7058 LIST_DEL(&kwl->list);
7059 LIST_INIT(&kwl->list);
7060}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007061
7062/*
7063 * Local variables:
7064 * c-indent-level: 8
7065 * c-basic-offset: 8
7066 * End:
7067 */