blob: abcb9c5866819db4745a425583e98fe609b39bd8 [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]);
905 if (compress_min_idle < 0 || compress_min_idle > 100) {
906 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;
1512 goto out;
1513 }
1514
Willy Tarreaufab5a432011-03-04 15:31:53 +01001515 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001516 free(raddr);
1517 if (!sk) {
1518 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001523 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001524 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001525 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001526
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001527 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001528 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1529 file, linenum, newpeer->addr.ss_family, args[2]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001534 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001535
1536 if (strcmp(newpeer->id, localpeer) == 0) {
1537 /* Current is local peer, it define a frontend */
1538 newpeer->local = 1;
1539
1540 if (!curpeers->peers_fe) {
1541 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1542 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1543 err_code |= ERR_ALERT | ERR_ABORT;
1544 goto out;
1545 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001546
Willy Tarreau237250c2011-07-29 01:49:03 +02001547 init_new_proxy(curpeers->peers_fe);
1548 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001549
1550 curpeers->peers_fe->last_change = now.tv_sec;
1551 curpeers->peers_fe->id = strdup(args[1]);
1552 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001553 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001554 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1555 curpeers->peers_fe->timeout.connect = 5000;
1556 curpeers->peers_fe->accept = peer_accept;
1557 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001558
1559 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1560
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001561 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1562 if (err_msg && *err_msg) {
1563 indent_msg(&err_msg, 2);
1564 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1565 }
1566 else
1567 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1568 file, linenum, args[0], args[1], args[2]);
1569 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001570 err_code |= ERR_FATAL;
1571 goto out;
1572 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001573
1574 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1575 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1576 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1577 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1578 l->accept = session_accept;
1579 l->handler = process_session;
1580 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1581 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1582 global.maxsock += l->maxconn;
1583 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001584 }
1585 }
1586 } /* neither "peer" nor "peers" */
1587 else if (*args[0] != 0) {
1588 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1589 err_code |= ERR_ALERT | ERR_FATAL;
1590 goto out;
1591 }
1592
1593out:
1594 return err_code;
1595}
1596
1597
Willy Tarreau3842f002009-06-14 11:39:52 +02001598int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599{
1600 static struct proxy *curproxy = NULL;
1601 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001602 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001603 int rc;
1604 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001605 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001606 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001607 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001608 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001609 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610
Willy Tarreau977b8e42006-12-29 14:19:17 +01001611 if (!strcmp(args[0], "listen"))
1612 rc = PR_CAP_LISTEN;
1613 else if (!strcmp(args[0], "frontend"))
1614 rc = PR_CAP_FE | PR_CAP_RS;
1615 else if (!strcmp(args[0], "backend"))
1616 rc = PR_CAP_BE | PR_CAP_RS;
1617 else if (!strcmp(args[0], "ruleset"))
1618 rc = PR_CAP_RS;
1619 else
1620 rc = PR_CAP_NONE;
1621
1622 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 if (!*args[1]) {
1624 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1625 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_ABORT;
1628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001630
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001631 err = invalid_char(args[1]);
1632 if (err) {
1633 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1634 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001635 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001636 }
1637
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001638 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1639 /*
1640 * If there are two proxies with the same name only following
1641 * combinations are allowed:
1642 *
1643 * listen backend frontend ruleset
1644 * listen - - - -
1645 * backend - - OK -
1646 * frontend - OK - -
1647 * ruleset - - - -
1648 */
1649
1650 if (!strcmp(curproxy->id, args[1]) &&
1651 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1652 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001653 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1654 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1655 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001656 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001657 }
1658 }
1659
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1661 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_ALERT | ERR_ABORT;
1663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001665
Willy Tarreau97cb7802010-01-03 20:23:58 +01001666 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 curproxy->next = proxy;
1668 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001669 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001670 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001671 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001673 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674
1675 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001676 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001677 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001678 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001679
Willy Tarreau4348fad2012-09-20 16:48:07 +02001680 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1681
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001682 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1683 if (err_msg && *err_msg) {
1684 indent_msg(&err_msg, 2);
1685 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1686 }
1687 else
1688 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1689 file, linenum, args[0], args[1], args[2]);
1690 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001691 err_code |= ERR_FATAL;
1692 goto out;
1693 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001694
Willy Tarreau4348fad2012-09-20 16:48:07 +02001695 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001696 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 }
1699
1700 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001701 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001702 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001703
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001706 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001707 curproxy->no_options = defproxy.no_options;
1708 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001709 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001710 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001711 curproxy->except_net = defproxy.except_net;
1712 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001713 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001714 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001716 if (defproxy.fwdfor_hdr_len) {
1717 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1718 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1719 }
1720
Willy Tarreaub86db342009-11-30 11:50:16 +01001721 if (defproxy.orgto_hdr_len) {
1722 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1723 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1724 }
1725
Mark Lamourinec2247f02012-01-04 13:02:01 -05001726 if (defproxy.server_id_hdr_len) {
1727 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1728 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1729 }
1730
Willy Tarreau977b8e42006-12-29 14:19:17 +01001731 if (curproxy->cap & PR_CAP_FE) {
1732 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001733 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001734 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001735
1736 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001737 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1738 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001739
1740 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742
Willy Tarreau977b8e42006-12-29 14:19:17 +01001743 if (curproxy->cap & PR_CAP_BE) {
1744 curproxy->fullconn = defproxy.fullconn;
1745 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001747 if (defproxy.check_req) {
1748 curproxy->check_req = calloc(1, defproxy.check_len);
1749 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1750 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001751 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001753 if (defproxy.expect_str) {
1754 curproxy->expect_str = strdup(defproxy.expect_str);
1755 if (defproxy.expect_regex) {
1756 /* note: this regex is known to be valid */
1757 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1758 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1759 }
1760 }
1761
Willy Tarreau67402132012-05-31 20:40:20 +02001762 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763 if (defproxy.cookie_name)
1764 curproxy->cookie_name = strdup(defproxy.cookie_name);
1765 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001766 if (defproxy.cookie_domain)
1767 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001768
Willy Tarreau31936852010-10-06 16:59:56 +02001769 if (defproxy.cookie_maxidle)
1770 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1771
1772 if (defproxy.cookie_maxlife)
1773 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1774
Emeric Brun647caf12009-06-30 17:57:00 +02001775 if (defproxy.rdp_cookie_name)
1776 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1777 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1778
Willy Tarreau01732802007-11-01 22:48:15 +01001779 if (defproxy.url_param_name)
1780 curproxy->url_param_name = strdup(defproxy.url_param_name);
1781 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001782
Benoitaffb4812009-03-25 13:02:10 +01001783 if (defproxy.hh_name)
1784 curproxy->hh_name = strdup(defproxy.hh_name);
1785 curproxy->hh_len = defproxy.hh_len;
1786 curproxy->hh_match_domain = defproxy.hh_match_domain;
1787
Willy Tarreauef9a3602012-12-08 22:29:20 +01001788 if (defproxy.conn_src.iface_name)
1789 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1790 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1791 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001794 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001795 if (defproxy.capture_name)
1796 curproxy->capture_name = strdup(defproxy.capture_name);
1797 curproxy->capture_namelen = defproxy.capture_namelen;
1798 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800
Willy Tarreau977b8e42006-12-29 14:19:17 +01001801 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001802 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001803 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001804 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001805 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001806 curproxy->uri_auth = defproxy.uri_auth;
1807 curproxy->mon_net = defproxy.mon_net;
1808 curproxy->mon_mask = defproxy.mon_mask;
1809 if (defproxy.monitor_uri)
1810 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1811 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001812 if (defproxy.defbe.name)
1813 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001814
1815 /* get either a pointer to the logformat string or a copy of it */
1816 curproxy->logformat_string = defproxy.logformat_string;
1817 if (curproxy->logformat_string &&
1818 curproxy->logformat_string != default_http_log_format &&
1819 curproxy->logformat_string != default_tcp_log_format &&
1820 curproxy->logformat_string != clf_http_log_format)
1821 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001822 }
1823
1824 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001825 curproxy->timeout.connect = defproxy.timeout.connect;
1826 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001827 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001828 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001829 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001830 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001831 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001832 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001833 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001834 }
1835
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001837
1838 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001839 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001840 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001841 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001842 LIST_INIT(&node->list);
1843 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1844 }
1845
Willy Tarreau196729e2012-05-31 19:30:26 +02001846 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1847 if (curproxy->uniqueid_format_string)
1848 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001849
1850 /* copy default header unique id */
1851 if (defproxy.header_unique_id)
1852 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1853
William Lallemand82fe75c2012-10-23 10:25:10 +02001854 /* default compression options */
1855 if (defproxy.comp != NULL) {
1856 curproxy->comp = calloc(1, sizeof(struct comp));
1857 curproxy->comp->algos = defproxy.comp->algos;
1858 curproxy->comp->types = defproxy.comp->types;
1859 }
1860
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001862 curproxy->conf.used_listener_id = EB_ROOT;
1863 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001864
Willy Tarreau93893792009-07-23 13:19:11 +02001865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 }
1867 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1868 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001869 /* FIXME-20070101: we should do this too at the end of the
1870 * config parsing to free all default values.
1871 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001872 free(defproxy.check_req);
1873 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001874 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001875 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001876 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001877 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001878 free(defproxy.capture_name);
1879 free(defproxy.monitor_uri);
1880 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001881 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001882 free(defproxy.fwdfor_hdr_name);
1883 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001884 free(defproxy.orgto_hdr_name);
1885 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001886 free(defproxy.server_id_hdr_name);
1887 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001888 free(defproxy.expect_str);
1889 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001890
Willy Tarreau39b06652012-06-01 10:58:06 +02001891 if (defproxy.logformat_string != default_http_log_format &&
1892 defproxy.logformat_string != default_tcp_log_format &&
1893 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001894 free(defproxy.logformat_string);
1895
1896 free(defproxy.uniqueid_format_string);
1897
Willy Tarreaua534fea2008-08-03 12:19:50 +02001898 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001899 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001900
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 /* we cannot free uri_auth because it might already be used */
1902 init_default_instance();
1903 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001904 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 }
1907 else if (curproxy == NULL) {
1908 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 }
1912
Willy Tarreau977b8e42006-12-29 14:19:17 +01001913
1914 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001916 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001917 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001918 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001919
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 if (curproxy == &defproxy) {
1921 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001925 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001926 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927
Emeric Bruned760922010-10-22 17:59:25 +02001928 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001929 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001934
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001935 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001936 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001937
1938 /* NOTE: the following line might create several listeners if there
1939 * are comma-separated IPs or port ranges. So all further processing
1940 * will have to be applied to all listeners created after last_listen.
1941 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001942 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1943 if (err_msg && *err_msg) {
1944 indent_msg(&err_msg, 2);
1945 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1946 }
1947 else
1948 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1949 file, linenum, args[0], args[1]);
1950 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001951 err_code |= ERR_ALERT | ERR_FATAL;
1952 goto out;
1953 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001954
Willy Tarreau4348fad2012-09-20 16:48:07 +02001955 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1956 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001957 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001958 }
1959
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001960 cur_arg = 2;
1961 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001962 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001963 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001964 char *err;
1965
Willy Tarreau26982662012-09-12 23:17:10 +02001966 kw = bind_find_kw(args[cur_arg]);
1967 if (kw) {
1968 char *err = NULL;
1969 int code;
1970
1971 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001972 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1973 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001974 cur_arg += 1 + kw->skip ;
1975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
1977 }
1978
Willy Tarreau4348fad2012-09-20 16:48:07 +02001979 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001980 err_code |= code;
1981
1982 if (code) {
1983 if (err && *err) {
1984 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001985 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001986 }
1987 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001988 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1989 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001990 if (code & ERR_FATAL) {
1991 free(err);
1992 cur_arg += 1 + kw->skip;
1993 goto out;
1994 }
1995 }
1996 free(err);
1997 cur_arg += 1 + kw->skip;
1998 continue;
1999 }
2000
Willy Tarreau8638f482012-09-18 18:01:17 +02002001 err = NULL;
2002 if (!bind_dumped) {
2003 bind_dump_kws(&err);
2004 indent_msg(&err, 4);
2005 bind_dumped = 1;
2006 }
2007
2008 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2009 file, linenum, args[0], args[1], args[cur_arg],
2010 err ? " Registered keywords :" : "", err ? err : "");
2011 free(err);
2012
Willy Tarreau93893792009-07-23 13:19:11 +02002013 err_code |= ERR_ALERT | ERR_FATAL;
2014 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002015 }
Willy Tarreau93893792009-07-23 13:19:11 +02002016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017 }
2018 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2019 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2020 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2021 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002022 err_code |= ERR_ALERT | ERR_FATAL;
2023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002025 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002027
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 /* flush useless bits */
2029 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002032 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002033 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002035
Willy Tarreau1c47f852006-07-09 08:22:27 +02002036 if (!*args[1]) {
2037 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002041 }
2042
Willy Tarreaua534fea2008-08-03 12:19:50 +02002043 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002044 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002045 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002046 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002047 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2048
Willy Tarreau93893792009-07-23 13:19:11 +02002049 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2052 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2053 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2054 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2055 else {
2056 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_ALERT | ERR_FATAL;
2058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 }
2060 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002061 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002062 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002063
2064 if (curproxy == &defproxy) {
2065 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2066 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_ALERT | ERR_FATAL;
2068 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002069 }
2070
2071 if (!*args[1]) {
2072 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2073 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002076 }
2077
2078 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002079 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002080
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002081 if (curproxy->uuid <= 0) {
2082 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002083 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002084 err_code |= ERR_ALERT | ERR_FATAL;
2085 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002086 }
2087
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002088 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2089 if (node) {
2090 struct proxy *target = container_of(node, struct proxy, conf.id);
2091 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2092 file, linenum, proxy_type_str(curproxy), curproxy->id,
2093 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
2096 }
2097 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002098 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002099 else if (!strcmp(args[0], "description")) {
2100 int i, len=0;
2101 char *d;
2102
Cyril Bonté99ed3272010-01-24 23:29:44 +01002103 if (curproxy == &defproxy) {
2104 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2105 file, linenum, args[0]);
2106 err_code |= ERR_ALERT | ERR_FATAL;
2107 goto out;
2108 }
2109
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002110 if (!*args[1]) {
2111 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2112 file, linenum, args[0]);
2113 return -1;
2114 }
2115
2116 for(i=1; *args[i]; i++)
2117 len += strlen(args[i])+1;
2118
2119 d = (char *)calloc(1, len);
2120 curproxy->desc = d;
2121
2122 d += sprintf(d, "%s", args[1]);
2123 for(i=2; *args[i]; i++)
2124 d += sprintf(d, " %s", args[i]);
2125
2126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002127 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2128 curproxy->state = PR_STSTOPPED;
2129 }
2130 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2131 curproxy->state = PR_STNEW;
2132 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002133 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2134 int cur_arg = 1;
2135 unsigned int set = 0;
2136
2137 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002138 unsigned int low, high;
2139
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002140 if (strcmp(args[cur_arg], "all") == 0) {
2141 set = 0;
2142 break;
2143 }
2144 else if (strcmp(args[cur_arg], "odd") == 0) {
2145 set |= 0x55555555;
2146 }
2147 else if (strcmp(args[cur_arg], "even") == 0) {
2148 set |= 0xAAAAAAAA;
2149 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002150 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002151 char *dash = strchr(args[cur_arg], '-');
2152
2153 low = high = str2uic(args[cur_arg]);
2154 if (dash)
2155 high = str2uic(dash + 1);
2156
2157 if (high < low) {
2158 unsigned int swap = low;
2159 low = high;
2160 high = swap;
2161 }
2162
2163 if (low < 1 || high > 32) {
2164 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002165 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002168 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002169
2170 if (high > global.nbproc) {
2171 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2172 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002173 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002174 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002175 while (low <= high)
2176 set |= 1 << (low++ - 1);
2177 }
2178 else {
2179 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2180 file, linenum, args[0]);
2181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002183 }
2184 cur_arg++;
2185 }
2186 curproxy->bind_proc = set;
2187 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002188 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002189 if (curproxy == &defproxy) {
2190 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002193 }
2194
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002195 err = invalid_char(args[1]);
2196 if (err) {
2197 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2198 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002200 }
2201
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002202 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2203 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2204 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002207 }
2208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2210 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211
Willy Tarreau977b8e42006-12-29 14:19:17 +01002212 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002213 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002214
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 if (*(args[1]) == 0) {
2216 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2217 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002221
Willy Tarreau67402132012-05-31 20:40:20 +02002222 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002223 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002224 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002225 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 curproxy->cookie_name = strdup(args[1]);
2227 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002228
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 cur_arg = 2;
2230 while (*(args[cur_arg])) {
2231 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002232 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 }
2234 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002235 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 }
2237 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002238 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 }
2240 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002241 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 }
2243 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002244 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002246 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002247 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002250 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002252 else if (!strcmp(args[cur_arg], "httponly")) {
2253 curproxy->ck_opts |= PR_CK_HTTPONLY;
2254 }
2255 else if (!strcmp(args[cur_arg], "secure")) {
2256 curproxy->ck_opts |= PR_CK_SECURE;
2257 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002258 else if (!strcmp(args[cur_arg], "domain")) {
2259 if (!*args[cur_arg + 1]) {
2260 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2261 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002264 }
2265
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002266 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002267 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002268 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2269 " dots nor does not start with a dot."
2270 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002271 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002272 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002273 }
2274
2275 err = invalid_domainchar(args[cur_arg + 1]);
2276 if (err) {
2277 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2278 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002281 }
2282
Willy Tarreau68a897b2009-12-03 23:28:34 +01002283 if (!curproxy->cookie_domain) {
2284 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2285 } else {
2286 /* one domain was already specified, add another one by
2287 * building the string which will be returned along with
2288 * the cookie.
2289 */
2290 char *new_ptr;
2291 int new_len = strlen(curproxy->cookie_domain) +
2292 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2293 new_ptr = malloc(new_len);
2294 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2295 free(curproxy->cookie_domain);
2296 curproxy->cookie_domain = new_ptr;
2297 }
Willy Tarreau31936852010-10-06 16:59:56 +02002298 cur_arg++;
2299 }
2300 else if (!strcmp(args[cur_arg], "maxidle")) {
2301 unsigned int maxidle;
2302 const char *res;
2303
2304 if (!*args[cur_arg + 1]) {
2305 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2306 file, linenum, args[cur_arg]);
2307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
2309 }
2310
2311 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2312 if (res) {
2313 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2314 file, linenum, *res, args[cur_arg]);
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318 curproxy->cookie_maxidle = maxidle;
2319 cur_arg++;
2320 }
2321 else if (!strcmp(args[cur_arg], "maxlife")) {
2322 unsigned int maxlife;
2323 const char *res;
2324
2325 if (!*args[cur_arg + 1]) {
2326 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2327 file, linenum, args[cur_arg]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331
2332 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2333 if (res) {
2334 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2335 file, linenum, *res, args[cur_arg]);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
2339 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002340 cur_arg++;
2341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002343 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 +02002344 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 }
2348 cur_arg++;
2349 }
Willy Tarreau67402132012-05-31 20:40:20 +02002350 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2352 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002353 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 }
2355
Willy Tarreau67402132012-05-31 20:40:20 +02002356 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2358 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002361
Willy Tarreau67402132012-05-31 20:40:20 +02002362 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002363 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2364 file, linenum);
2365 err_code |= ERR_ALERT | ERR_FATAL;
2366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002368 else if (!strcmp(args[0], "persist")) { /* persist */
2369 if (*(args[1]) == 0) {
2370 Alert("parsing [%s:%d] : missing persist method.\n",
2371 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002374 }
2375
2376 if (!strncmp(args[1], "rdp-cookie", 10)) {
2377 curproxy->options2 |= PR_O2_RDPC_PRST;
2378
Emeric Brunb982a3d2010-01-04 15:45:53 +01002379 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002380 const char *beg, *end;
2381
2382 beg = args[1] + 11;
2383 end = strchr(beg, ')');
2384
2385 if (!end || end == beg) {
2386 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2387 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002390 }
2391
2392 free(curproxy->rdp_cookie_name);
2393 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2394 curproxy->rdp_cookie_len = end-beg;
2395 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002396 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002397 free(curproxy->rdp_cookie_name);
2398 curproxy->rdp_cookie_name = strdup("msts");
2399 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2400 }
2401 else { /* syntax */
2402 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2403 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002406 }
2407 }
2408 else {
2409 Alert("parsing [%s:%d] : unknown persist method.\n",
2410 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002413 }
2414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002416 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002418 if (curproxy == &defproxy) {
2419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
2422 }
2423
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002426
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002428 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002434 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 curproxy->appsession_name = strdup(args[1]);
2436 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2437 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002438 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2439 if (err) {
2440 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2441 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002444 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002445 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002446
Willy Tarreau51041c72007-09-09 21:56:53 +02002447 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2448 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002449 err_code |= ERR_ALERT | ERR_ABORT;
2450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002452
2453 cur_arg = 6;
2454 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002455 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2456 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002457 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002458 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002459 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002460 } else if (!strcmp(args[cur_arg], "prefix")) {
2461 curproxy->options2 |= PR_O2_AS_PFX;
2462 } else if (!strcmp(args[cur_arg], "mode")) {
2463 if (!*args[cur_arg + 1]) {
2464 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2465 file, linenum, args[0], args[cur_arg]);
2466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
2469
2470 cur_arg++;
2471 if (!strcmp(args[cur_arg], "query-string")) {
2472 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2473 curproxy->options2 |= PR_O2_AS_M_QS;
2474 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2475 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2476 curproxy->options2 |= PR_O2_AS_M_PP;
2477 } else {
2478 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2479 err_code |= ERR_ALERT | ERR_FATAL;
2480 goto out;
2481 }
2482 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002483 cur_arg++;
2484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 } /* Url App Session */
2486 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002487 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002488 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002489
Willy Tarreaubaaee002006-06-26 02:48:02 +02002490 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002491 if (curproxy == &defproxy) {
2492 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 if (*(args[4]) == 0) {
2498 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2499 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002503 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 curproxy->capture_name = strdup(args[2]);
2505 curproxy->capture_namelen = strlen(curproxy->capture_name);
2506 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 curproxy->to_log |= LW_COOKIE;
2508 }
2509 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2510 struct cap_hdr *hdr;
2511
2512 if (curproxy == &defproxy) {
2513 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 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 }
2517
2518 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2519 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2520 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
2524
2525 hdr = calloc(sizeof(struct cap_hdr), 1);
2526 hdr->next = curproxy->req_cap;
2527 hdr->name = strdup(args[3]);
2528 hdr->namelen = strlen(args[3]);
2529 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002530 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 hdr->index = curproxy->nb_req_cap++;
2532 curproxy->req_cap = hdr;
2533 curproxy->to_log |= LW_REQHDR;
2534 }
2535 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2536 struct cap_hdr *hdr;
2537
2538 if (curproxy == &defproxy) {
2539 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 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 }
2543
2544 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2545 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2546 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 }
2550 hdr = calloc(sizeof(struct cap_hdr), 1);
2551 hdr->next = curproxy->rsp_cap;
2552 hdr->name = strdup(args[3]);
2553 hdr->namelen = strlen(args[3]);
2554 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002555 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 hdr->index = curproxy->nb_rsp_cap++;
2557 curproxy->rsp_cap = hdr;
2558 curproxy->to_log |= LW_RSPHDR;
2559 }
2560 else {
2561 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2562 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 }
2566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002568 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002570
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 if (*(args[1]) == 0) {
2572 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2573 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 }
2577 curproxy->conn_retries = atol(args[1]);
2578 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002579 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002580 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002581
2582 if (curproxy == &defproxy) {
2583 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
2586 }
2587
Willy Tarreau20b0de52012-12-24 15:45:22 +01002588 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2589 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2590 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2591 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2592 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2593 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 +01002594 file, linenum, args[0]);
2595 err_code |= ERR_WARN;
2596 }
2597
Willy Tarreauff011f22011-01-06 17:51:27 +01002598 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002599
Willy Tarreauff011f22011-01-06 17:51:27 +01002600 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002601 err_code |= ERR_ALERT | ERR_ABORT;
2602 goto out;
2603 }
2604
Willy Tarreauff011f22011-01-06 17:51:27 +01002605 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2606 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002607 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002608 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2609 /* set the header name and length into the proxy structure */
2610 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2611 err_code |= ERR_WARN;
2612
2613 if (!*args[1]) {
2614 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2615 file, linenum, args[0]);
2616 err_code |= ERR_ALERT | ERR_FATAL;
2617 goto out;
2618 }
2619
2620 /* set the desired header name */
2621 free(curproxy->server_id_hdr_name);
2622 curproxy->server_id_hdr_name = strdup(args[1]);
2623 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2624 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002625 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002626 if (curproxy == &defproxy) {
2627 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002630 }
2631
Willy Tarreauef6494c2010-01-28 17:12:36 +01002632 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002633 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2634 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002637 }
2638
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002639 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2640 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2641 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002644 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002645
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002646 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002647 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002648 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002649 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002650 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002651
Cyril Bonté99ed3272010-01-24 23:29:44 +01002652 if (curproxy == &defproxy) {
2653 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
2656 }
2657
Willy Tarreau4baae242012-12-27 12:00:31 +01002658 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2659 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2660 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002663 }
2664
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002665 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002666 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2667 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002668 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002669 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002670 struct switching_rule *rule;
2671
Willy Tarreaub099aca2008-10-12 17:26:37 +02002672 if (curproxy == &defproxy) {
2673 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002676 }
2677
Willy Tarreau55ea7572007-06-17 19:56:27 +02002678 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002679 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002680
2681 if (*(args[1]) == 0) {
2682 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002685 }
2686
Willy Tarreauef6494c2010-01-28 17:12:36 +01002687 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002688 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2689 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002692 }
2693
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002694 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2695 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2696 file, linenum, errmsg);
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 Tarreauf1e98b82010-01-28 17:59:39 +01002701 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002702
Willy Tarreau55ea7572007-06-17 19:56:27 +02002703 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2704 rule->cond = cond;
2705 rule->be.name = strdup(args[1]);
2706 LIST_INIT(&rule->list);
2707 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2708 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002709 else if (strcmp(args[0], "use-server") == 0) {
2710 struct server_rule *rule;
2711
2712 if (curproxy == &defproxy) {
2713 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
2716 }
2717
2718 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2719 err_code |= ERR_WARN;
2720
2721 if (*(args[1]) == 0) {
2722 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
2725 }
2726
2727 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2728 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2729 file, linenum, args[0]);
2730 err_code |= ERR_ALERT | ERR_FATAL;
2731 goto out;
2732 }
2733
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002734 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2735 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2736 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740
2741 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2742
2743 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2744 rule->cond = cond;
2745 rule->srv.name = strdup(args[1]);
2746 LIST_INIT(&rule->list);
2747 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2748 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2749 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002750 else if ((!strcmp(args[0], "force-persist")) ||
2751 (!strcmp(args[0], "ignore-persist"))) {
2752 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002753
2754 if (curproxy == &defproxy) {
2755 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
2758 }
2759
2760 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2761 err_code |= ERR_WARN;
2762
Willy Tarreauef6494c2010-01-28 17:12:36 +01002763 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002764 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2765 file, linenum, args[0]);
2766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002770 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2771 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2772 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
2775 }
2776
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002777 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002778
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002779 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002780 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002781 if (!strcmp(args[0], "force-persist")) {
2782 rule->type = PERSIST_TYPE_FORCE;
2783 } else {
2784 rule->type = PERSIST_TYPE_IGNORE;
2785 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002786 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002787 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002788 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002789 else if (!strcmp(args[0], "stick-table")) {
2790 int myidx = 1;
2791
Emeric Brun32da3c42010-09-23 18:39:19 +02002792 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002793 curproxy->table.type = (unsigned int)-1;
2794 while (*args[myidx]) {
2795 const char *err;
2796
2797 if (strcmp(args[myidx], "size") == 0) {
2798 myidx++;
2799 if (!*(args[myidx])) {
2800 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2801 file, linenum, args[myidx-1]);
2802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
2804 }
2805 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2806 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2807 file, linenum, *err, args[myidx-1]);
2808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
2810 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002811 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002812 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002813 else if (strcmp(args[myidx], "peers") == 0) {
2814 myidx++;
2815 if (!*(args[myidx])) {
2816 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2817 file, linenum, args[myidx-1]);
2818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
2820 }
2821 curproxy->table.peers.name = strdup(args[myidx++]);
2822 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002823 else if (strcmp(args[myidx], "expire") == 0) {
2824 myidx++;
2825 if (!*(args[myidx])) {
2826 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2827 file, linenum, args[myidx-1]);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830 }
2831 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2832 if (err) {
2833 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2834 file, linenum, *err, args[myidx-1]);
2835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
2837 }
2838 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002839 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002840 }
2841 else if (strcmp(args[myidx], "nopurge") == 0) {
2842 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002843 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002844 }
2845 else if (strcmp(args[myidx], "type") == 0) {
2846 myidx++;
2847 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2848 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2849 file, linenum, args[myidx]);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002853 /* myidx already points to next arg */
2854 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002855 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002856 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002857 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002858
2859 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002860 nw = args[myidx];
2861 while (*nw) {
2862 /* the "store" keyword supports a comma-separated list */
2863 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002864 sa = NULL; /* store arg */
2865 while (*nw && *nw != ',') {
2866 if (*nw == '(') {
2867 *nw = 0;
2868 sa = ++nw;
2869 while (*nw != ')') {
2870 if (!*nw) {
2871 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2872 file, linenum, args[0], cw);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876 nw++;
2877 }
2878 *nw = '\0';
2879 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002880 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002881 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002882 if (*nw)
2883 *nw++ = '\0';
2884 type = stktable_get_data_type(cw);
2885 if (type < 0) {
2886 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2887 file, linenum, args[0], cw);
2888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
Willy Tarreauac782882010-06-20 10:41:54 +02002891
2892 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2893 switch (err) {
2894 case PE_NONE: break;
2895 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002896 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2897 file, linenum, args[0], cw);
2898 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002899 break;
2900
2901 case PE_ARG_MISSING:
2902 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2903 file, linenum, args[0], cw);
2904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
2906
2907 case PE_ARG_NOT_USED:
2908 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2909 file, linenum, args[0], cw);
2910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
2912
2913 default:
2914 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2915 file, linenum, args[0], cw);
2916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002918 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002919 }
2920 myidx++;
2921 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002922 else {
2923 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2924 file, linenum, args[myidx]);
2925 err_code |= ERR_ALERT | ERR_FATAL;
2926 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002927 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002928 }
2929
2930 if (!curproxy->table.size) {
2931 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2932 file, linenum);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936
2937 if (curproxy->table.type == (unsigned int)-1) {
2938 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2939 file, linenum);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
2943 }
2944 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002945 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002946 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002947 int myidx = 0;
2948 const char *name = NULL;
2949 int flags;
2950
2951 if (curproxy == &defproxy) {
2952 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2953 err_code |= ERR_ALERT | ERR_FATAL;
2954 goto out;
2955 }
2956
2957 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2958 err_code |= ERR_WARN;
2959 goto out;
2960 }
2961
2962 myidx++;
2963 if ((strcmp(args[myidx], "store") == 0) ||
2964 (strcmp(args[myidx], "store-request") == 0)) {
2965 myidx++;
2966 flags = STK_IS_STORE;
2967 }
2968 else if (strcmp(args[myidx], "store-response") == 0) {
2969 myidx++;
2970 flags = STK_IS_STORE | STK_ON_RSP;
2971 }
2972 else if (strcmp(args[myidx], "match") == 0) {
2973 myidx++;
2974 flags = STK_IS_MATCH;
2975 }
2976 else if (strcmp(args[myidx], "on") == 0) {
2977 myidx++;
2978 flags = STK_IS_MATCH | STK_IS_STORE;
2979 }
2980 else {
2981 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
2984 }
2985
2986 if (*(args[myidx]) == 0) {
2987 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002992 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002993 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002994 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
2997 }
2998
2999 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003000 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003001 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3002 file, linenum, args[0], expr->fetch->kw);
3003 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003004 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003005 goto out;
3006 }
3007 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003008 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003009 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3010 file, linenum, args[0], expr->fetch->kw);
3011 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003012 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003013 goto out;
3014 }
3015 }
3016
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003017 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3018 if (expr->fetch->cap & SMP_CAP_L7)
3019 curproxy->acl_requires |= ACL_USE_L7_ANY;
3020
Emeric Brunb982a3d2010-01-04 15:45:53 +01003021 if (strcmp(args[myidx], "table") == 0) {
3022 myidx++;
3023 name = args[myidx++];
3024 }
3025
Willy Tarreauef6494c2010-01-28 17:12:36 +01003026 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003027 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3028 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3029 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003030 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003031 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003032 goto out;
3033 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003034 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003035 else if (*(args[myidx])) {
3036 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3037 file, linenum, args[0], args[myidx]);
3038 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003039 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003040 goto out;
3041 }
Emeric Brun97679e72010-09-23 17:56:44 +02003042 if (flags & STK_ON_RSP)
3043 err_code |= warnif_cond_requires_req(cond, file, linenum);
3044 else
3045 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003046
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3048 rule->cond = cond;
3049 rule->expr = expr;
3050 rule->flags = flags;
3051 rule->table.name = name ? strdup(name) : NULL;
3052 LIST_INIT(&rule->list);
3053 if (flags & STK_ON_RSP)
3054 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3055 else
3056 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003059 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003061
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3063 curproxy->uri_auth = NULL; /* we must detach from the default config */
3064
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003065 if (!*args[1]) {
3066 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003067 } else if (!strcmp(args[1], "admin")) {
3068 struct stats_admin_rule *rule;
3069
3070 if (curproxy == &defproxy) {
3071 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
3074 }
3075
3076 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3077 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3078 err_code |= ERR_ALERT | ERR_ABORT;
3079 goto out;
3080 }
3081
3082 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3083 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3084 file, linenum, args[0], args[1]);
3085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
3087 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003088 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3089 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3090 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
3094
3095 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3096
3097 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3098 rule->cond = cond;
3099 LIST_INIT(&rule->list);
3100 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 } else if (!strcmp(args[1], "uri")) {
3102 if (*(args[2]) == 0) {
3103 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003104 err_code |= ERR_ALERT | ERR_FATAL;
3105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3107 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_ABORT;
3109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 }
3111 } else if (!strcmp(args[1], "realm")) {
3112 if (*(args[2]) == 0) {
3113 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3117 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_ALERT | ERR_ABORT;
3119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003121 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003122 unsigned interval;
3123
3124 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3125 if (err) {
3126 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3127 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003130 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
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 Tarreaubbd42122007-07-25 07:26:38 +02003134 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003135 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003136 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003137
3138 if (curproxy == &defproxy) {
3139 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
3142 }
3143
3144 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3145 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3146 err_code |= ERR_ALERT | ERR_ABORT;
3147 goto out;
3148 }
3149
Willy Tarreauff011f22011-01-06 17:51:27 +01003150 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3151 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003152 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3153 file, linenum, args[0]);
3154 err_code |= ERR_WARN;
3155 }
3156
Willy Tarreauff011f22011-01-06 17:51:27 +01003157 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003158
Willy Tarreauff011f22011-01-06 17:51:27 +01003159 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003160 err_code |= ERR_ALERT | ERR_ABORT;
3161 goto out;
3162 }
3163
Willy Tarreauff011f22011-01-06 17:51:27 +01003164 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3165 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003166
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 } else if (!strcmp(args[1], "auth")) {
3168 if (*(args[2]) == 0) {
3169 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_ALERT | ERR_FATAL;
3171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3173 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_ABORT;
3175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 }
3177 } else if (!strcmp(args[1], "scope")) {
3178 if (*(args[2]) == 0) {
3179 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3183 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_ABORT;
3185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 }
3187 } else if (!strcmp(args[1], "enable")) {
3188 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3189 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003190 err_code |= ERR_ALERT | ERR_ABORT;
3191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003193 } else if (!strcmp(args[1], "hide-version")) {
3194 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3195 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_ABORT;
3197 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003198 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003199 } else if (!strcmp(args[1], "show-legends")) {
3200 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3201 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3202 err_code |= ERR_ALERT | ERR_ABORT;
3203 goto out;
3204 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003205 } else if (!strcmp(args[1], "show-node")) {
3206
3207 if (*args[2]) {
3208 int i;
3209 char c;
3210
3211 for (i=0; args[2][i]; i++) {
3212 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003213 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3214 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003215 break;
3216 }
3217
3218 if (!i || args[2][i]) {
3219 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3220 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3221 file, linenum, args[0], args[1]);
3222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
3224 }
3225 }
3226
3227 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3228 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3229 err_code |= ERR_ALERT | ERR_ABORT;
3230 goto out;
3231 }
3232 } else if (!strcmp(args[1], "show-desc")) {
3233 char *desc = NULL;
3234
3235 if (*args[2]) {
3236 int i, len=0;
3237 char *d;
3238
3239 for(i=2; *args[i]; i++)
3240 len += strlen(args[i])+1;
3241
3242 desc = d = (char *)calloc(1, len);
3243
3244 d += sprintf(d, "%s", args[2]);
3245 for(i=3; *args[i]; i++)
3246 d += sprintf(d, " %s", args[i]);
3247 }
3248
3249 if (!*args[2] && !global.desc)
3250 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3251 file, linenum, args[1]);
3252 else {
3253 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3254 free(desc);
3255 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3256 err_code |= ERR_ALERT | ERR_ABORT;
3257 goto out;
3258 }
3259 free(desc);
3260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003262stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003263 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 +01003264 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 }
3268 }
3269 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003270 int optnum;
3271
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003272 if (*(args[1]) == '\0') {
3273 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3274 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003278
3279 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3280 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003281 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3282 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3283 file, linenum, cfg_opts[optnum].name);
3284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
3286 }
Willy Tarreau93893792009-07-23 13:19:11 +02003287 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3288 err_code |= ERR_WARN;
3289 goto out;
3290 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003291
Willy Tarreau3842f002009-06-14 11:39:52 +02003292 curproxy->no_options &= ~cfg_opts[optnum].val;
3293 curproxy->options &= ~cfg_opts[optnum].val;
3294
3295 switch (kwm) {
3296 case KWM_STD:
3297 curproxy->options |= cfg_opts[optnum].val;
3298 break;
3299 case KWM_NO:
3300 curproxy->no_options |= cfg_opts[optnum].val;
3301 break;
3302 case KWM_DEF: /* already cleared */
3303 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003304 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003305
Willy Tarreau93893792009-07-23 13:19:11 +02003306 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307 }
3308 }
3309
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003310 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3311 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003312 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3313 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3314 file, linenum, cfg_opts2[optnum].name);
3315 err_code |= ERR_ALERT | ERR_FATAL;
3316 goto out;
3317 }
Willy Tarreau93893792009-07-23 13:19:11 +02003318 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3319 err_code |= ERR_WARN;
3320 goto out;
3321 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003322
Willy Tarreau3842f002009-06-14 11:39:52 +02003323 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3324 curproxy->options2 &= ~cfg_opts2[optnum].val;
3325
3326 switch (kwm) {
3327 case KWM_STD:
3328 curproxy->options2 |= cfg_opts2[optnum].val;
3329 break;
3330 case KWM_NO:
3331 curproxy->no_options2 |= cfg_opts2[optnum].val;
3332 break;
3333 case KWM_DEF: /* already cleared */
3334 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003335 }
Willy Tarreau93893792009-07-23 13:19:11 +02003336 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003337 }
3338 }
3339
Willy Tarreau3842f002009-06-14 11:39:52 +02003340 if (kwm != KWM_STD) {
3341 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003342 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003345 }
3346
Emeric Brun3a058f32009-06-30 18:26:00 +02003347 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003348 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003350 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003351 if (*(args[2]) != '\0') {
3352 if (!strcmp(args[2], "clf")) {
3353 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003354 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003355 } else {
3356 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003359 }
3360 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003361 if (curproxy->logformat_string != default_http_log_format &&
3362 curproxy->logformat_string != default_tcp_log_format &&
3363 curproxy->logformat_string != clf_http_log_format)
3364 free(curproxy->logformat_string);
3365 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003366 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003367 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003369 if (curproxy->logformat_string != default_http_log_format &&
3370 curproxy->logformat_string != default_tcp_log_format &&
3371 curproxy->logformat_string != clf_http_log_format)
3372 free(curproxy->logformat_string);
3373 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003374 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 else if (!strcmp(args[1], "tcpka")) {
3376 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003377 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003379
3380 if (curproxy->cap & PR_CAP_FE)
3381 curproxy->options |= PR_O_TCP_CLI_KA;
3382 if (curproxy->cap & PR_CAP_BE)
3383 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 }
3385 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003386 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_WARN;
3388
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003390 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003391 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003392 curproxy->options2 &= ~PR_O2_CHK_ANY;
3393 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 if (!*args[2]) { /* no argument */
3395 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3396 curproxy->check_len = strlen(DEF_CHECK_REQ);
3397 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003398 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 curproxy->check_req = (char *)malloc(reqlen);
3400 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003401 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003403 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 if (*args[4])
3405 reqlen += strlen(args[4]);
3406 else
3407 reqlen += strlen("HTTP/1.0");
3408
3409 curproxy->check_req = (char *)malloc(reqlen);
3410 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003411 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003413 }
3414 else if (!strcmp(args[1], "ssl-hello-chk")) {
3415 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003416 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003417 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003418
Willy Tarreaua534fea2008-08-03 12:19:50 +02003419 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003420 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003421 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003422 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 }
Willy Tarreau23677902007-05-08 23:50:35 +02003424 else if (!strcmp(args[1], "smtpchk")) {
3425 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003426 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003427 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003428 curproxy->options2 &= ~PR_O2_CHK_ANY;
3429 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003430
3431 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3432 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3433 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3434 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3435 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3436 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3437 curproxy->check_req = (char *)malloc(reqlen);
3438 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3439 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3440 } else {
3441 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3442 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3443 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3444 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3445 }
3446 }
3447 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003448 else if (!strcmp(args[1], "pgsql-check")) {
3449 /* use PostgreSQL request to check servers' health */
3450 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3451 err_code |= ERR_WARN;
3452
3453 free(curproxy->check_req);
3454 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003455 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003456 curproxy->options2 |= PR_O2_PGSQL_CHK;
3457
3458 if (*(args[2])) {
3459 int cur_arg = 2;
3460
3461 while (*(args[cur_arg])) {
3462 if (strcmp(args[cur_arg], "user") == 0) {
3463 char * packet;
3464 uint32_t packet_len;
3465 uint32_t pv;
3466
3467 /* suboption header - needs additional argument for it */
3468 if (*(args[cur_arg+1]) == 0) {
3469 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3470 file, linenum, args[0], args[1], args[cur_arg]);
3471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
3473 }
3474
3475 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3476 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3477 pv = htonl(0x30000); /* protocol version 3.0 */
3478
3479 packet = (char*) calloc(1, packet_len);
3480
3481 memcpy(packet + 4, &pv, 4);
3482
3483 /* copy "user" */
3484 memcpy(packet + 8, "user", 4);
3485
3486 /* copy username */
3487 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3488
3489 free(curproxy->check_req);
3490 curproxy->check_req = packet;
3491 curproxy->check_len = packet_len;
3492
3493 packet_len = htonl(packet_len);
3494 memcpy(packet, &packet_len, 4);
3495 cur_arg += 2;
3496 } else {
3497 /* unknown suboption - catchall */
3498 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3499 file, linenum, args[0], args[1]);
3500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
3502 }
3503 } /* end while loop */
3504 }
3505 }
3506
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003507 else if (!strcmp(args[1], "redis-check")) {
3508 /* use REDIS PING request to check servers' health */
3509 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3510 err_code |= ERR_WARN;
3511
3512 free(curproxy->check_req);
3513 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003514 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003515 curproxy->options2 |= PR_O2_REDIS_CHK;
3516
3517 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3518 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3519 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3520 }
3521
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003522 else if (!strcmp(args[1], "mysql-check")) {
3523 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003524 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3525 err_code |= ERR_WARN;
3526
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003527 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003528 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003529 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003530 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003531
3532 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3533 * const char mysql40_client_auth_pkt[] = {
3534 * "\x0e\x00\x00" // packet length
3535 * "\x01" // packet number
3536 * "\x00\x00" // client capabilities
3537 * "\x00\x00\x01" // max packet
3538 * "haproxy\x00" // username (null terminated string)
3539 * "\x00" // filler (always 0x00)
3540 * "\x01\x00\x00" // packet length
3541 * "\x00" // packet number
3542 * "\x01" // COM_QUIT command
3543 * };
3544 */
3545
3546 if (*(args[2])) {
3547 int cur_arg = 2;
3548
3549 while (*(args[cur_arg])) {
3550 if (strcmp(args[cur_arg], "user") == 0) {
3551 char *mysqluser;
3552 int packetlen, reqlen, userlen;
3553
3554 /* suboption header - needs additional argument for it */
3555 if (*(args[cur_arg+1]) == 0) {
3556 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3557 file, linenum, args[0], args[1], args[cur_arg]);
3558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
3560 }
3561 mysqluser = args[cur_arg + 1];
3562 userlen = strlen(mysqluser);
3563 packetlen = userlen + 7;
3564 reqlen = packetlen + 9;
3565
3566 free(curproxy->check_req);
3567 curproxy->check_req = (char *)calloc(1, reqlen);
3568 curproxy->check_len = reqlen;
3569
3570 snprintf(curproxy->check_req, 4, "%c%c%c",
3571 ((unsigned char) packetlen & 0xff),
3572 ((unsigned char) (packetlen >> 8) & 0xff),
3573 ((unsigned char) (packetlen >> 16) & 0xff));
3574
3575 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003576 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003577 curproxy->check_req[8] = 1;
3578 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3579 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3580 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3581 cur_arg += 2;
3582 } else {
3583 /* unknown suboption - catchall */
3584 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3585 file, linenum, args[0], args[1]);
3586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
3588 }
3589 } /* end while loop */
3590 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003591 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003592 else if (!strcmp(args[1], "ldap-check")) {
3593 /* use LDAP request to check servers' health */
3594 free(curproxy->check_req);
3595 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003596 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003597 curproxy->options2 |= PR_O2_LDAP_CHK;
3598
3599 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3600 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3601 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3602 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003603 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003604 int cur_arg;
3605
3606 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3607 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003608 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003609
Willy Tarreau87cf5142011-08-19 22:57:24 +02003610 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003611
3612 free(curproxy->fwdfor_hdr_name);
3613 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3614 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3615
3616 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3617 cur_arg = 2;
3618 while (*(args[cur_arg])) {
3619 if (!strcmp(args[cur_arg], "except")) {
3620 /* suboption except - needs additional argument for it */
3621 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3622 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3623 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003626 }
3627 /* flush useless bits */
3628 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003629 cur_arg += 2;
3630 } else if (!strcmp(args[cur_arg], "header")) {
3631 /* suboption header - needs additional argument for it */
3632 if (*(args[cur_arg+1]) == 0) {
3633 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3634 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003637 }
3638 free(curproxy->fwdfor_hdr_name);
3639 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3640 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3641 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003642 } else if (!strcmp(args[cur_arg], "if-none")) {
3643 curproxy->options &= ~PR_O_FF_ALWAYS;
3644 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003645 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003646 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003647 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003648 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003651 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003652 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003653 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003654 else if (!strcmp(args[1], "originalto")) {
3655 int cur_arg;
3656
3657 /* insert x-original-to field, but not for the IP address listed as an except.
3658 * set default options (ie: bitfield, header name, etc)
3659 */
3660
3661 curproxy->options |= PR_O_ORGTO;
3662
3663 free(curproxy->orgto_hdr_name);
3664 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3665 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3666
Willy Tarreau87cf5142011-08-19 22:57:24 +02003667 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003668 cur_arg = 2;
3669 while (*(args[cur_arg])) {
3670 if (!strcmp(args[cur_arg], "except")) {
3671 /* suboption except - needs additional argument for it */
3672 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3673 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3674 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003677 }
3678 /* flush useless bits */
3679 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3680 cur_arg += 2;
3681 } else if (!strcmp(args[cur_arg], "header")) {
3682 /* suboption header - needs additional argument for it */
3683 if (*(args[cur_arg+1]) == 0) {
3684 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3685 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003688 }
3689 free(curproxy->orgto_hdr_name);
3690 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3691 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3692 cur_arg += 2;
3693 } else {
3694 /* unknown suboption - catchall */
3695 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3696 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003699 }
3700 } /* end while loop */
3701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 else {
3703 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003706 }
Willy Tarreau93893792009-07-23 13:19:11 +02003707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003709 else if (!strcmp(args[0], "default_backend")) {
3710 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003712
3713 if (*(args[1]) == 0) {
3714 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003715 err_code |= ERR_ALERT | ERR_FATAL;
3716 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003717 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003718 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003719 curproxy->defbe.name = strdup(args[1]);
3720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003722 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003723 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003724
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003725 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 /* enable reconnections to dispatch */
3729 curproxy->options |= PR_O_REDISP;
3730 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003731 else if (!strcmp(args[0], "http-check")) {
3732 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003734
3735 if (strcmp(args[1], "disable-on-404") == 0) {
3736 /* enable a graceful server shutdown on an HTTP 404 response */
3737 curproxy->options |= PR_O_DISABLE404;
3738 }
Willy Tarreauef781042010-01-27 11:53:01 +01003739 else if (strcmp(args[1], "send-state") == 0) {
3740 /* enable emission of the apparent state of a server in HTTP checks */
3741 curproxy->options2 |= PR_O2_CHK_SNDST;
3742 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003743 else if (strcmp(args[1], "expect") == 0) {
3744 const char *ptr_arg;
3745 int cur_arg;
3746
3747 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3748 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
3751 }
3752
3753 cur_arg = 2;
3754 /* consider exclamation marks, sole or at the beginning of a word */
3755 while (*(ptr_arg = args[cur_arg])) {
3756 while (*ptr_arg == '!') {
3757 curproxy->options2 ^= PR_O2_EXP_INV;
3758 ptr_arg++;
3759 }
3760 if (*ptr_arg)
3761 break;
3762 cur_arg++;
3763 }
3764 /* now ptr_arg points to the beginning of a word past any possible
3765 * exclamation mark, and cur_arg is the argument which holds this word.
3766 */
3767 if (strcmp(ptr_arg, "status") == 0) {
3768 if (!*(args[cur_arg + 1])) {
3769 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3770 file, linenum, args[0], args[1], ptr_arg);
3771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
3773 }
3774 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003775 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003776 curproxy->expect_str = strdup(args[cur_arg + 1]);
3777 }
3778 else if (strcmp(ptr_arg, "string") == 0) {
3779 if (!*(args[cur_arg + 1])) {
3780 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3781 file, linenum, args[0], args[1], ptr_arg);
3782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
3784 }
3785 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003786 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003787 curproxy->expect_str = strdup(args[cur_arg + 1]);
3788 }
3789 else if (strcmp(ptr_arg, "rstatus") == 0) {
3790 if (!*(args[cur_arg + 1])) {
3791 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3792 file, linenum, args[0], args[1], ptr_arg);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
3796 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003797 free(curproxy->expect_str);
3798 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3799 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003800 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3801 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3802 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3803 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
3806 }
3807 }
3808 else if (strcmp(ptr_arg, "rstring") == 0) {
3809 if (!*(args[cur_arg + 1])) {
3810 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3811 file, linenum, args[0], args[1], ptr_arg);
3812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
3814 }
3815 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003816 free(curproxy->expect_str);
3817 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3818 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003819 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3820 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3821 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3822 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
3825 }
3826 }
3827 else {
3828 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3829 file, linenum, args[0], args[1], ptr_arg);
3830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
3832 }
3833 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003834 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003835 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 +02003836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003838 }
3839 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003840 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003841 if (curproxy == &defproxy) {
3842 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003845 }
3846
Willy Tarreaub80c2302007-11-30 20:51:32 +01003847 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003849
3850 if (strcmp(args[1], "fail") == 0) {
3851 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003852 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003853 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3854 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003857 }
3858
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003859 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3860 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3861 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003864 }
3865 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3866 }
3867 else {
3868 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
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 Tarreaubaaee002006-06-26 02:48:02 +02003873#ifdef TPROXY
3874 else if (!strcmp(args[0], "transparent")) {
3875 /* enable transparent proxy connections */
3876 curproxy->options |= PR_O_TRANSP;
3877 }
3878#endif
3879 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003880 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003881 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003882
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883 if (*(args[1]) == 0) {
3884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 }
3888 curproxy->maxconn = atol(args[1]);
3889 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003890 else if (!strcmp(args[0], "backlog")) { /* backlog */
3891 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003893
3894 if (*(args[1]) == 0) {
3895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003898 }
3899 curproxy->backlog = atol(args[1]);
3900 }
Willy Tarreau86034312006-12-29 00:10:33 +01003901 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003902 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003904
Willy Tarreau86034312006-12-29 00:10:33 +01003905 if (*(args[1]) == 0) {
3906 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003909 }
3910 curproxy->fullconn = atol(args[1]);
3911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003912 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3913 if (*(args[1]) == 0) {
3914 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003918 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3919 if (err) {
3920 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3921 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003924 }
3925 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926 }
3927 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003928 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003929 if (curproxy == &defproxy) {
3930 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003934 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003936
Willy Tarreaubaaee002006-06-26 02:48:02 +02003937 if (strchr(args[1], ':') == NULL) {
3938 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003941 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003942 sk = str2sa(args[1]);
3943 if (!sk) {
3944 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
3948 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003949 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 }
3951 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003952 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003954
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003955 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3956 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003959 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003961 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3962 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3963 err_code |= ERR_WARN;
3964
3965 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3966 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3967 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3968 }
3969 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3970 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3971 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3972 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003973 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3974 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3975 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3976 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003977 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003978 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
3982 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003983 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003984 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003985 char *rport, *raddr;
3986 short realport = 0;
3987 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003988
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003989 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003994 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996
3997 if (!*args[2]) {
3998 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3999 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004003
4004 err = invalid_char(args[1]);
4005 if (err) {
4006 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4007 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004010 }
4011
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004012 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004013 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004014
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004015 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4016 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4017 err_code |= ERR_ALERT | ERR_ABORT;
4018 goto out;
4019 }
4020
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004021 /* the servers are linked backwards first */
4022 newsrv->next = curproxy->srv;
4023 curproxy->srv = newsrv;
4024 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004025 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004026 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004027
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004028 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004029 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004030 LIST_INIT(&newsrv->pendconns);
4031 do_check = 0;
4032 newsrv->state = SRV_RUNNING; /* early server setup */
4033 newsrv->last_change = now.tv_sec;
4034 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004036 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004037 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004038 * - IP: => port=+0, relative
4039 * - IP:N => port=N, absolute
4040 * - IP:+N => port=+N, relative
4041 * - IP:-N => port=-N, relative
4042 */
4043 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004044 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004045 if (rport) {
4046 *rport++ = 0;
4047 realport = atol(rport);
4048 if (!isdigit((unsigned char)*rport))
4049 newsrv->state |= SRV_MAPPORTS;
4050 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004052
Willy Tarreaufab5a432011-03-04 15:31:53 +01004053 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004054 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004055 if (!sk) {
4056 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
4059 }
4060 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004061 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4062 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004063
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004064 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004065 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4066 file, linenum, newsrv->addr.ss_family, args[2]);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004070 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004071
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004072 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004073 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004074 newsrv->inter = curproxy->defsrv.inter;
4075 newsrv->fastinter = curproxy->defsrv.fastinter;
4076 newsrv->downinter = curproxy->defsrv.downinter;
4077 newsrv->rise = curproxy->defsrv.rise;
4078 newsrv->fall = curproxy->defsrv.fall;
4079 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4080 newsrv->minconn = curproxy->defsrv.minconn;
4081 newsrv->maxconn = curproxy->defsrv.maxconn;
4082 newsrv->slowstart = curproxy->defsrv.slowstart;
4083 newsrv->onerror = curproxy->defsrv.onerror;
4084 newsrv->consecutive_errors_limit
4085 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004086#ifdef OPENSSL
4087 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4088#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004089 newsrv->uweight = newsrv->iweight
4090 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004091
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004092 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004093
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004094 cur_arg = 3;
4095 } else {
4096 newsrv = &curproxy->defsrv;
4097 cur_arg = 1;
4098 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004099
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004101 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004102 newsrv->cookie = strdup(args[cur_arg + 1]);
4103 newsrv->cklen = strlen(args[cur_arg + 1]);
4104 cur_arg += 2;
4105 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004106 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004107 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4108 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4109 cur_arg += 2;
4110 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004111 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004112 if (!*args[cur_arg + 1]) {
4113 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4114 file, linenum, args[cur_arg]);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
4118
Willy Tarreaubaaee002006-06-26 02:48:02 +02004119 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004120 if (newsrv->rise <= 0) {
4121 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4122 file, linenum, args[cur_arg]);
4123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
4125 }
4126
Willy Tarreau96839092010-03-29 10:02:24 +02004127 if (newsrv->health)
4128 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004129 cur_arg += 2;
4130 }
4131 else if (!strcmp(args[cur_arg], "fall")) {
4132 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004133
4134 if (!*args[cur_arg + 1]) {
4135 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4136 file, linenum, args[cur_arg]);
4137 err_code |= ERR_ALERT | ERR_FATAL;
4138 goto out;
4139 }
4140
4141 if (newsrv->fall <= 0) {
4142 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4143 file, linenum, args[cur_arg]);
4144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
4146 }
4147
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 cur_arg += 2;
4149 }
4150 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004151 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4152 if (err) {
4153 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4154 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004155 err_code |= ERR_ALERT | ERR_FATAL;
4156 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004157 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004158 if (val <= 0) {
4159 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4160 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004163 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004164 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 cur_arg += 2;
4166 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004167 else if (!strcmp(args[cur_arg], "fastinter")) {
4168 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4169 if (err) {
4170 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4171 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004174 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004175 if (val <= 0) {
4176 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4177 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004180 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004181 newsrv->fastinter = val;
4182 cur_arg += 2;
4183 }
4184 else if (!strcmp(args[cur_arg], "downinter")) {
4185 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4186 if (err) {
4187 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4188 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004189 err_code |= ERR_ALERT | ERR_FATAL;
4190 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004191 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004192 if (val <= 0) {
4193 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4194 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004197 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004198 newsrv->downinter = val;
4199 cur_arg += 2;
4200 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004201 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004202 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004203 if (!sk) {
4204 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
4207 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004208 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004209 cur_arg += 2;
4210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004212 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004213 cur_arg += 2;
4214 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004215 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004216 newsrv->state |= SRV_BACKUP;
4217 cur_arg ++;
4218 }
Simon Hormanfa461682011-06-25 09:39:49 +09004219 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4220 newsrv->state |= SRV_NON_STICK;
4221 cur_arg ++;
4222 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004223 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4224 newsrv->state |= SRV_SEND_PROXY;
4225 cur_arg ++;
4226 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004227 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4228 newsrv->check.send_proxy = 1;
4229 cur_arg ++;
4230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231 else if (!strcmp(args[cur_arg], "weight")) {
4232 int w;
4233 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004234 if (w < 0 || w > 256) {
4235 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004236 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004239 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004240 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004241 cur_arg += 2;
4242 }
4243 else if (!strcmp(args[cur_arg], "minconn")) {
4244 newsrv->minconn = atol(args[cur_arg + 1]);
4245 cur_arg += 2;
4246 }
4247 else if (!strcmp(args[cur_arg], "maxconn")) {
4248 newsrv->maxconn = atol(args[cur_arg + 1]);
4249 cur_arg += 2;
4250 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004251 else if (!strcmp(args[cur_arg], "maxqueue")) {
4252 newsrv->maxqueue = atol(args[cur_arg + 1]);
4253 cur_arg += 2;
4254 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004255 else if (!strcmp(args[cur_arg], "slowstart")) {
4256 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004257 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004258 if (err) {
4259 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4260 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004261 err_code |= ERR_ALERT | ERR_FATAL;
4262 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004263 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004264 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004265 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4266 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004269 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004270 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004271 cur_arg += 2;
4272 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004273 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004274
4275 if (!*args[cur_arg + 1]) {
4276 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4277 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004280 }
4281
4282 newsrv->trackit = strdup(args[cur_arg + 1]);
4283
4284 cur_arg += 2;
4285 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004286 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004287 global.maxsock++;
4288 do_check = 1;
4289 cur_arg += 1;
4290 }
Willy Tarreau96839092010-03-29 10:02:24 +02004291 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4292 newsrv->state |= SRV_MAINTAIN;
4293 newsrv->state &= ~SRV_RUNNING;
4294 newsrv->health = 0;
4295 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004296 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004297 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004298 if (!strcmp(args[cur_arg + 1], "none"))
4299 newsrv->observe = HANA_OBS_NONE;
4300 else if (!strcmp(args[cur_arg + 1], "layer4"))
4301 newsrv->observe = HANA_OBS_LAYER4;
4302 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4303 if (curproxy->mode != PR_MODE_HTTP) {
4304 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4305 file, linenum, args[cur_arg + 1]);
4306 err_code |= ERR_ALERT;
4307 }
4308 newsrv->observe = HANA_OBS_LAYER7;
4309 }
4310 else {
4311 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004312 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004313 file, linenum, args[cur_arg], args[cur_arg + 1]);
4314 err_code |= ERR_ALERT | ERR_FATAL;
4315 goto out;
4316 }
4317
4318 cur_arg += 2;
4319 }
4320 else if (!strcmp(args[cur_arg], "on-error")) {
4321 if (!strcmp(args[cur_arg + 1], "fastinter"))
4322 newsrv->onerror = HANA_ONERR_FASTINTER;
4323 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4324 newsrv->onerror = HANA_ONERR_FAILCHK;
4325 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4326 newsrv->onerror = HANA_ONERR_SUDDTH;
4327 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4328 newsrv->onerror = HANA_ONERR_MARKDWN;
4329 else {
4330 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004331 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004332 file, linenum, args[cur_arg], args[cur_arg + 1]);
4333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
4335 }
4336
4337 cur_arg += 2;
4338 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004339 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4340 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4341 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4342 else {
4343 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4344 file, linenum, args[cur_arg], args[cur_arg + 1]);
4345 err_code |= ERR_ALERT | ERR_FATAL;
4346 goto out;
4347 }
4348
4349 cur_arg += 2;
4350 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004351 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4352 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4353 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4354 else {
4355 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4356 file, linenum, args[cur_arg], args[cur_arg + 1]);
4357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
4359 }
4360
4361 cur_arg += 2;
4362 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004363 else if (!strcmp(args[cur_arg], "error-limit")) {
4364 if (!*args[cur_arg + 1]) {
4365 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4366 file, linenum, args[cur_arg]);
4367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
4369 }
4370
4371 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4372
4373 if (newsrv->consecutive_errors_limit <= 0) {
4374 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4375 file, linenum, args[cur_arg]);
4376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
4378 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004379 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004380 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004381 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004382 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004383 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004384
Willy Tarreaubaaee002006-06-26 02:48:02 +02004385 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004386 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4387 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004390 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004391 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004392 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4393 if (!sk) {
4394 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
4397 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004398 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004399
4400 if (port_low != port_high) {
4401 int i;
4402 if (port_low <= 0 || port_low > 65535 ||
4403 port_high <= 0 || port_high > 65535 ||
4404 port_low > port_high) {
4405 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4406 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004409 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004410 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4411 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4412 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004413 }
4414
Willy Tarreaubaaee002006-06-26 02:48:02 +02004415 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004416 while (*(args[cur_arg])) {
4417 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004418#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4419#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004420 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004421 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4422 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004423 err_code |= ERR_ALERT | ERR_FATAL;
4424 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004425 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004426#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004427 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004428 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004429 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004432 }
4433 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004434 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4435 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004436 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004437 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4438 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004439 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4440 char *name, *end;
4441
4442 name = args[cur_arg+1] + 7;
4443 while (isspace(*name))
4444 name++;
4445
4446 end = name;
4447 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4448 end++;
4449
Willy Tarreauef9a3602012-12-08 22:29:20 +01004450 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4451 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4452 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4453 newsrv->conn_src.bind_hdr_len = end - name;
4454 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4455 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4456 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004457
4458 /* now look for an occurrence number */
4459 while (isspace(*end))
4460 end++;
4461 if (*end == ',') {
4462 end++;
4463 name = end;
4464 if (*end == '-')
4465 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004466 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004467 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004468 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004469 }
4470
Willy Tarreauef9a3602012-12-08 22:29:20 +01004471 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004472 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4473 " occurrences values smaller than %d.\n",
4474 file, linenum, MAX_HDR_HISTORY);
4475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
4477 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004478 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004479 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004480 if (!sk) {
4481 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
4484 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004485 newsrv->conn_src.tproxy_addr = *sk;
4486 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004487 }
4488 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004489#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004490 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004491#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004492 cur_arg += 2;
4493 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004494#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004495 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004496 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004497 err_code |= ERR_ALERT | ERR_FATAL;
4498 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004499#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4500 } /* "usesrc" */
4501
4502 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4503#ifdef SO_BINDTODEVICE
4504 if (!*args[cur_arg + 1]) {
4505 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4506 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004509 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004510 free(newsrv->conn_src.iface_name);
4511 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4512 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004513 global.last_checks |= LSTCHK_NETADM;
4514#else
4515 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4516 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004517 err_code |= ERR_ALERT | ERR_FATAL;
4518 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004519#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004520 cur_arg += 2;
4521 continue;
4522 }
4523 /* this keyword in not an option of "source" */
4524 break;
4525 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004527 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004528 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4529 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004532 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004533 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004534 static int srv_dumped;
4535 struct srv_kw *kw;
4536 char *err;
4537
4538 kw = srv_find_kw(args[cur_arg]);
4539 if (kw) {
4540 char *err = NULL;
4541 int code;
4542
4543 if (!kw->parse) {
4544 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4545 file, linenum, args[0], args[1], args[cur_arg]);
4546 cur_arg += 1 + kw->skip ;
4547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
4549 }
4550
4551 if (defsrv && !kw->default_ok) {
4552 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4553 file, linenum, args[0], args[1], args[cur_arg]);
4554 cur_arg += 1 + kw->skip ;
4555 err_code |= ERR_ALERT;
4556 continue;
4557 }
4558
4559 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4560 err_code |= code;
4561
4562 if (code) {
4563 if (err && *err) {
4564 indent_msg(&err, 2);
4565 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4566 }
4567 else
4568 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4569 file, linenum, args[0], args[1], args[cur_arg]);
4570 if (code & ERR_FATAL) {
4571 free(err);
4572 cur_arg += 1 + kw->skip;
4573 goto out;
4574 }
4575 }
4576 free(err);
4577 cur_arg += 1 + kw->skip;
4578 continue;
4579 }
4580
4581 err = NULL;
4582 if (!srv_dumped) {
4583 srv_dump_kws(&err);
4584 indent_msg(&err, 4);
4585 srv_dumped = 1;
4586 }
4587
4588 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4589 file, linenum, args[0], args[1], args[cur_arg],
4590 err ? " Registered keywords :" : "", err ? err : "");
4591 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004592
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 }
4596 }
4597
4598 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004599 if (newsrv->trackit) {
4600 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4601 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004604 }
4605
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004606 /* If neither a port nor an addr was specified and no check transport
4607 * layer is forced, then the transport layer used by the checks is the
4608 * same as for the production traffic. Otherwise we use raw_sock by
4609 * default, unless one is specified.
4610 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004611 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004612#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004613 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004614#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004615 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4616 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004617 /* try to get the port from check.addr if check.port not set */
4618 if (!newsrv->check.port)
4619 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004620
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004621 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4622 newsrv->check.port = realport; /* by default */
4623 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004624 /* not yet valid, because no port was set on
4625 * the server either. We'll check if we have
4626 * a known port on the first listener.
4627 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004628 struct listener *l;
4629
4630 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004631 newsrv->check.port = get_host_port(&l->addr);
4632 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004633 break;
4634 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004635 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004636 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004637 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4638 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004642
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004643 /* Allocate buffer for check requests... */
4644 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004645 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4646 err_code |= ERR_ALERT | ERR_ABORT;
4647 goto out;
4648 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004649 newsrv->check.bi->size = global.tune.chksize;
4650
4651 /* Allocate buffer for check responses... */
4652 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4653 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 }
4657 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004658
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004659 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004660 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004661 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4662 err_code |= ERR_ALERT | ERR_ABORT;
4663 goto out;
4664 }
4665
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004666 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4667 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 newsrv->state |= SRV_CHECKED;
4669 }
4670
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004671 if (!defsrv) {
4672 if (newsrv->state & SRV_BACKUP)
4673 curproxy->srv_bck++;
4674 else
4675 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004676
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004677 newsrv->prev_state = newsrv->state;
4678 }
William Lallemanda73203e2012-03-12 12:48:57 +01004679 }
4680
4681 else if (strcmp(args[0], "unique-id-format") == 0) {
4682 if (!*(args[1])) {
4683 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4684 err_code |= ERR_ALERT | ERR_FATAL;
4685 goto out;
4686 }
William Lallemand3203ff42012-11-11 17:30:56 +01004687 if (*(args[2])) {
4688 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
4691 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004692 free(curproxy->uniqueid_format_string);
4693 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004694 }
William Lallemanda73203e2012-03-12 12:48:57 +01004695
4696 else if (strcmp(args[0], "unique-id-header") == 0) {
4697 if (!*(args[1])) {
4698 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
4701 }
4702 free(curproxy->header_unique_id);
4703 curproxy->header_unique_id = strdup(args[1]);
4704 }
4705
William Lallemand723b73a2012-02-08 16:37:49 +01004706 else if (strcmp(args[0], "log-format") == 0) {
4707 if (!*(args[1])) {
4708 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4709 err_code |= ERR_ALERT | ERR_FATAL;
4710 goto out;
4711 }
William Lallemand3203ff42012-11-11 17:30:56 +01004712 if (*(args[2])) {
4713 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
4716 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004717
4718 if (curproxy->logformat_string != default_http_log_format &&
4719 curproxy->logformat_string != default_tcp_log_format &&
4720 curproxy->logformat_string != clf_http_log_format)
4721 free(curproxy->logformat_string);
4722 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 }
William Lallemand723b73a2012-02-08 16:37:49 +01004724
William Lallemand0f99e342011-10-12 17:50:54 +02004725 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4726 /* delete previous herited or defined syslog servers */
4727 struct logsrv *back;
4728
4729 if (*(args[1]) != 0) {
4730 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
4733 }
4734
William Lallemand723b73a2012-02-08 16:37:49 +01004735 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4736 LIST_DEL(&tmplogsrv->list);
4737 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004738 }
4739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004741 struct logsrv *logsrv;
4742
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004744 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004745 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004746 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004747 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004748 LIST_INIT(&node->list);
4749 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
4752 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004753
4754 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755
William Lallemand0f99e342011-10-12 17:50:54 +02004756 logsrv->facility = get_log_facility(args[2]);
4757 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
4761
Willy Tarreaubaaee002006-06-26 02:48:02 +02004762 }
4763
William Lallemand0f99e342011-10-12 17:50:54 +02004764 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004766 logsrv->level = get_log_level(args[3]);
4767 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
4771
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 }
4773 }
4774
William Lallemand0f99e342011-10-12 17:50:54 +02004775 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004776 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004777 logsrv->minlvl = get_log_level(args[4]);
4778 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004779 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004780 err_code |= ERR_ALERT | ERR_FATAL;
4781 goto out;
4782
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004783 }
4784 }
4785
Robert Tsai81ae1952007-12-05 10:47:29 +01004786 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004787 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004788 if (!sk) {
4789 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004790 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004791 err_code |= ERR_ALERT | ERR_FATAL;
4792 goto out;
4793 }
William Lallemand0f99e342011-10-12 17:50:54 +02004794 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004795 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004796 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004797 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004798 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
4801 }
William Lallemand0f99e342011-10-12 17:50:54 +02004802 logsrv->addr = *sk;
4803 if (!get_host_port(&logsrv->addr))
4804 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004805 }
William Lallemand0f99e342011-10-12 17:50:54 +02004806
4807 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004808 }
4809 else {
4810 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4811 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004812 err_code |= ERR_ALERT | ERR_FATAL;
4813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 }
4815 }
4816 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004817 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004818 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004819
Willy Tarreau977b8e42006-12-29 14:19:17 +01004820 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004821 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004822
Willy Tarreaubaaee002006-06-26 02:48:02 +02004823 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004824 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4825 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004826 err_code |= ERR_ALERT | ERR_FATAL;
4827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004828 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004829
4830 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004831 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4832 free(curproxy->conn_src.iface_name);
4833 curproxy->conn_src.iface_name = NULL;
4834 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004835
Willy Tarreaud5191e72010-02-09 20:50:45 +01004836 sk = str2sa(args[1]);
4837 if (!sk) {
4838 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4839 err_code |= ERR_ALERT | ERR_FATAL;
4840 goto out;
4841 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004842 curproxy->conn_src.source_addr = *sk;
4843 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004844
4845 cur_arg = 2;
4846 while (*(args[cur_arg])) {
4847 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004848#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4849#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004850 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004851 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4852 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004853 err_code |= ERR_ALERT | ERR_FATAL;
4854 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004855 }
4856#endif
4857 if (!*args[cur_arg + 1]) {
4858 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4859 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004862 }
4863
4864 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004865 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4866 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004867 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004868 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4869 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004870 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4871 char *name, *end;
4872
4873 name = args[cur_arg+1] + 7;
4874 while (isspace(*name))
4875 name++;
4876
4877 end = name;
4878 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4879 end++;
4880
Willy Tarreauef9a3602012-12-08 22:29:20 +01004881 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4882 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4883 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4884 curproxy->conn_src.bind_hdr_len = end - name;
4885 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4886 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4887 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004888
4889 /* now look for an occurrence number */
4890 while (isspace(*end))
4891 end++;
4892 if (*end == ',') {
4893 end++;
4894 name = end;
4895 if (*end == '-')
4896 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004897 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004898 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004899 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004900 }
4901
Willy Tarreauef9a3602012-12-08 22:29:20 +01004902 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004903 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4904 " occurrences values smaller than %d.\n",
4905 file, linenum, MAX_HDR_HISTORY);
4906 err_code |= ERR_ALERT | ERR_FATAL;
4907 goto out;
4908 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004909 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004910 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004911 if (!sk) {
4912 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
4915 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004916 curproxy->conn_src.tproxy_addr = *sk;
4917 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004918 }
4919 global.last_checks |= LSTCHK_NETADM;
4920#if !defined(CONFIG_HAP_LINUX_TPROXY)
4921 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004922#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004923#else /* no TPROXY support */
4924 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004925 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004928#endif
4929 cur_arg += 2;
4930 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004931 }
4932
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004933 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4934#ifdef SO_BINDTODEVICE
4935 if (!*args[cur_arg + 1]) {
4936 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4937 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004940 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004941 free(curproxy->conn_src.iface_name);
4942 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4943 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004944 global.last_checks |= LSTCHK_NETADM;
4945#else
4946 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4947 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004950#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004951 cur_arg += 2;
4952 continue;
4953 }
4954 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004955 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004960 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4961 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4962 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4969 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004973
4974 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004975 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004976 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
4980 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004982 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004983 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004984 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 }
4987 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004989 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004990 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
4994 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004996 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004997 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
5001 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005003 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005004 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005008 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005010 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005011 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005012 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005013 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005014 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005015 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005016 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005017 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005018 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005019 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005020 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005021 }
5022 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005023 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005024 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005025 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005026 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005027 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005030 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5032 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005035 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036
5037 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005038 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005039 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005040 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005042 }
5043 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005044 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005045 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005046 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005047 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049 }
5050 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005051 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005052 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005053 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005054 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 }
5057 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005058 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005059 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005060 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005061 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063 }
5064 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005065 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005066 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005067 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005068 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005071 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005072 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005073 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005074 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005075 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005076 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005077 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005078 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005079 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005080
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 if (curproxy == &defproxy) {
5082 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005086 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 if (*(args[1]) == 0) {
5090 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\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 Tarreaudeb9ed82010-01-03 21:03:22 +01005094
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005095 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005096 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5097 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5098 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
5101 }
5102 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5103 }
5104 else if (*args[2]) {
5105 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5106 file, linenum, args[0], args[2]);
5107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
5110
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005111 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005112 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005113 wl->s = strdup(args[1]);
5114 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005115 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 }
5117 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005118 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5120 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005124
Willy Tarreauade5ec42010-01-28 19:33:49 +01005125 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005126 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005127 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005128 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005130 }
5131 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005132 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005133 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005134 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005135 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137 }
5138 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005139 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005140 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005141 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005142 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005144 }
5145 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005146 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5148 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151 }
5152
Willy Tarreauade5ec42010-01-28 19:33:49 +01005153 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005154 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005155 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005156 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
5159 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005160 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005161 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005162 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005163 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 }
5166 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005167 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005168 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005169 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005170 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 }
5173 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005174 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005175
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 if (curproxy == &defproxy) {
5177 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005181 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005182 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 if (*(args[1]) == 0) {
5185 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\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 }
5189
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005190 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005191 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5192 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5193 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
5196 }
5197 err_code |= warnif_cond_requires_req(cond, file, linenum);
5198 }
5199 else if (*args[2]) {
5200 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5201 file, linenum, args[0], args[2]);
5202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
5204 }
5205
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005206 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005207 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005208 wl->s = strdup(args[1]);
5209 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
5211 else if (!strcmp(args[0], "errorloc") ||
5212 !strcmp(args[0], "errorloc302") ||
5213 !strcmp(args[0], "errorloc303")) { /* error location */
5214 int errnum, errlen;
5215 char *err;
5216
Willy Tarreau977b8e42006-12-29 14:19:17 +01005217 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005218 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005219
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005221 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224 }
5225
5226 errnum = atol(args[1]);
5227 if (!strcmp(args[0], "errorloc303")) {
5228 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5229 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5230 } else {
5231 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5232 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5233 }
5234
Willy Tarreau0f772532006-12-23 20:51:41 +01005235 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5236 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005237 chunk_destroy(&curproxy->errmsg[rc]);
5238 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005239 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005242
5243 if (rc >= HTTP_ERR_SIZE) {
5244 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5245 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005246 free(err);
5247 }
5248 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005249 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5250 int errnum, errlen, fd;
5251 char *err;
5252 struct stat stat;
5253
5254 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005255 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005256
5257 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005258 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005261 }
5262
5263 fd = open(args[2], O_RDONLY);
5264 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5265 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5266 file, linenum, args[2], args[1]);
5267 if (fd >= 0)
5268 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005271 }
5272
Willy Tarreau27a674e2009-08-17 07:23:33 +02005273 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005274 errlen = stat.st_size;
5275 } else {
5276 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005277 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005278 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005279 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005280 }
5281
5282 err = malloc(errlen); /* malloc() must succeed during parsing */
5283 errnum = read(fd, err, errlen);
5284 if (errnum != errlen) {
5285 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5286 file, linenum, args[2], args[1]);
5287 close(fd);
5288 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005291 }
5292 close(fd);
5293
5294 errnum = atol(args[1]);
5295 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5296 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005297 chunk_destroy(&curproxy->errmsg[rc]);
5298 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005299 break;
5300 }
5301 }
5302
5303 if (rc >= HTTP_ERR_SIZE) {
5304 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5305 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005306 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005307 free(err);
5308 }
5309 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005310 else if (!strcmp(args[0], "compression")) {
5311 struct comp *comp;
5312 if (curproxy->comp == NULL) {
5313 comp = calloc(1, sizeof(struct comp));
5314 curproxy->comp = comp;
5315 } else {
5316 comp = curproxy->comp;
5317 }
5318
5319 if (!strcmp(args[1], "algo")) {
5320 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005321 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005322
William Lallemand82fe75c2012-10-23 10:25:10 +02005323 cur_arg = 2;
5324 if (!*args[cur_arg]) {
5325 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5326 file, linenum, args[0]);
5327 err_code |= ERR_ALERT | ERR_FATAL;
5328 goto out;
5329 }
5330 while (*(args[cur_arg])) {
5331 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5332 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5333 file, linenum, args[0], args[cur_arg]);
5334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336 }
William Lallemand552df672012-11-07 13:21:47 +01005337 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5338 curproxy->comp->algos->end(&ctx);
5339 } else {
5340 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5341 file, linenum, args[0], args[cur_arg]);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005345 cur_arg ++;
5346 continue;
5347 }
5348 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005349 else if (!strcmp(args[1], "offload")) {
5350 comp->offload = 1;
5351 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005352 else if (!strcmp(args[1], "type")) {
5353 int cur_arg;
5354 cur_arg = 2;
5355 if (!*args[cur_arg]) {
5356 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5357 file, linenum, args[0]);
5358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
5360 }
5361 while (*(args[cur_arg])) {
5362 comp_append_type(comp, args[cur_arg]);
5363 cur_arg ++;
5364 continue;
5365 }
5366 }
5367 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005368 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005369 file, linenum, args[0]);
5370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
5372 }
5373 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005374 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005375 struct cfg_kw_list *kwl;
5376 int index;
5377
5378 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5379 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5380 if (kwl->kw[index].section != CFG_LISTEN)
5381 continue;
5382 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5383 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005384 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005385 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005386 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005389 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005390 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005391 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005392 err_code |= ERR_WARN;
5393 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005394 }
Willy Tarreau93893792009-07-23 13:19:11 +02005395 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005396 }
5397 }
5398 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005399
Willy Tarreau6daf3432008-01-22 16:44:08 +01005400 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005401 err_code |= ERR_ALERT | ERR_FATAL;
5402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005403 }
Willy Tarreau93893792009-07-23 13:19:11 +02005404 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005405 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005406 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005407}
5408
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005409int
5410cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5411{
5412
5413 int err_code = 0;
5414 const char *err;
5415
5416 if (!strcmp(args[0], "userlist")) { /* new userlist */
5417 struct userlist *newul;
5418
5419 if (!*args[1]) {
5420 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5421 file, linenum, args[0]);
5422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
5424 }
5425
5426 err = invalid_char(args[1]);
5427 if (err) {
5428 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5429 file, linenum, *err, args[0], args[1]);
5430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
5432 }
5433
5434 for (newul = userlist; newul; newul = newul->next)
5435 if (!strcmp(newul->name, args[1])) {
5436 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5437 file, linenum, args[1]);
5438 err_code |= ERR_WARN;
5439 goto out;
5440 }
5441
5442 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5443 if (!newul) {
5444 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5445 err_code |= ERR_ALERT | ERR_ABORT;
5446 goto out;
5447 }
5448
5449 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5450 newul->name = strdup(args[1]);
5451
5452 if (!newul->groupusers | !newul->name) {
5453 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5454 err_code |= ERR_ALERT | ERR_ABORT;
5455 goto out;
5456 }
5457
5458 newul->next = userlist;
5459 userlist = newul;
5460
5461 } else if (!strcmp(args[0], "group")) { /* new group */
5462 int cur_arg, i;
5463 const char *err;
5464
5465 if (!*args[1]) {
5466 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5467 file, linenum, args[0]);
5468 err_code |= ERR_ALERT | ERR_FATAL;
5469 goto out;
5470 }
5471
5472 err = invalid_char(args[1]);
5473 if (err) {
5474 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5475 file, linenum, *err, args[0], args[1]);
5476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
5478 }
5479
5480 for(i = 0; i < userlist->grpcnt; i++)
5481 if (!strcmp(userlist->groups[i], args[1])) {
5482 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5483 file, linenum, args[1], userlist->name);
5484 err_code |= ERR_ALERT;
5485 goto out;
5486 }
5487
5488 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5489 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5490 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5491 err_code |= ERR_ALERT | ERR_FATAL;
5492 goto out;
5493 }
5494
5495 cur_arg = 2;
5496
5497 while (*args[cur_arg]) {
5498 if (!strcmp(args[cur_arg], "users")) {
5499 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5500 cur_arg += 2;
5501 continue;
5502 } else {
5503 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5504 file, linenum, args[0]);
5505 err_code |= ERR_ALERT | ERR_FATAL;
5506 goto out;
5507 }
5508 }
5509
5510 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5511 } else if (!strcmp(args[0], "user")) { /* new user */
5512 struct auth_users *newuser;
5513 int cur_arg;
5514
5515 if (!*args[1]) {
5516 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5517 file, linenum, args[0]);
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
5520 }
5521
5522 for (newuser = userlist->users; newuser; newuser = newuser->next)
5523 if (!strcmp(newuser->user, args[1])) {
5524 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5525 file, linenum, args[1], userlist->name);
5526 err_code |= ERR_ALERT;
5527 goto out;
5528 }
5529
5530 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5531 if (!newuser) {
5532 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5533 err_code |= ERR_ALERT | ERR_ABORT;
5534 goto out;
5535 }
5536
5537 newuser->user = strdup(args[1]);
5538
5539 newuser->next = userlist->users;
5540 userlist->users = newuser;
5541
5542 cur_arg = 2;
5543
5544 while (*args[cur_arg]) {
5545 if (!strcmp(args[cur_arg], "password")) {
5546#ifndef CONFIG_HAP_CRYPT
5547 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5548 file, linenum);
5549 err_code |= ERR_ALERT;
5550#endif
5551 newuser->pass = strdup(args[cur_arg + 1]);
5552 cur_arg += 2;
5553 continue;
5554 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5555 newuser->pass = strdup(args[cur_arg + 1]);
5556 newuser->flags |= AU_O_INSECURE;
5557 cur_arg += 2;
5558 continue;
5559 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005560 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005561 cur_arg += 2;
5562 continue;
5563 } else {
5564 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5565 file, linenum, args[0]);
5566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
5568 }
5569 }
5570 } else {
5571 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5572 err_code |= ERR_ALERT | ERR_FATAL;
5573 }
5574
5575out:
5576 return err_code;
5577}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578
5579/*
5580 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005581 * Returns the error code, 0 if OK, or any combination of :
5582 * - ERR_ABORT: must abort ASAP
5583 * - ERR_FATAL: we can continue parsing but not start the service
5584 * - ERR_WARN: a warning has been emitted
5585 * - ERR_ALERT: an alert has been emitted
5586 * Only the two first ones can stop processing, the two others are just
5587 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005589int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005591 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 FILE *f;
5593 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005595 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597 if ((f=fopen(file,"r")) == NULL)
5598 return -1;
5599
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005600 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005601 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005602 char *end;
5603 char *args[MAX_LINE_ARGS + 1];
5604 char *line = thisline;
5605
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 linenum++;
5607
5608 end = line + strlen(line);
5609
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005610 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5611 /* Check if we reached the limit and the last char is not \n.
5612 * Watch out for the last line without the terminating '\n'!
5613 */
5614 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005615 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005616 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005617 }
5618
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005620 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 line++;
5622
5623 arg = 0;
5624 args[arg] = line;
5625
5626 while (*line && arg < MAX_LINE_ARGS) {
5627 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5628 * C equivalent value. Other combinations left unchanged (eg: \1).
5629 */
5630 if (*line == '\\') {
5631 int skip = 0;
5632 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5633 *line = line[1];
5634 skip = 1;
5635 }
5636 else if (line[1] == 'r') {
5637 *line = '\r';
5638 skip = 1;
5639 }
5640 else if (line[1] == 'n') {
5641 *line = '\n';
5642 skip = 1;
5643 }
5644 else if (line[1] == 't') {
5645 *line = '\t';
5646 skip = 1;
5647 }
5648 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005649 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 unsigned char hex1, hex2;
5651 hex1 = toupper(line[2]) - '0';
5652 hex2 = toupper(line[3]) - '0';
5653 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5654 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5655 *line = (hex1<<4) + hex2;
5656 skip = 3;
5657 }
5658 else {
5659 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005660 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 }
5662 }
5663 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005664 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 end -= skip;
5666 }
5667 line++;
5668 }
5669 else if (*line == '#' || *line == '\n' || *line == '\r') {
5670 /* end of string, end of loop */
5671 *line = 0;
5672 break;
5673 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005674 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005676 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005677 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005678 line++;
5679 args[++arg] = line;
5680 }
5681 else {
5682 line++;
5683 }
5684 }
5685
5686 /* empty line */
5687 if (!**args)
5688 continue;
5689
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005690 if (*line) {
5691 /* we had to stop due to too many args.
5692 * Let's terminate the string, print the offending part then cut the
5693 * last arg.
5694 */
5695 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5696 line++;
5697 *line = '\0';
5698
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005699 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005700 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005701 err_code |= ERR_ALERT | ERR_FATAL;
5702 args[arg] = line;
5703 }
5704
Willy Tarreau540abe42007-05-02 20:50:16 +02005705 /* zero out remaining args and ensure that at least one entry
5706 * is zeroed out.
5707 */
5708 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 args[arg] = line;
5710 }
5711
Willy Tarreau3842f002009-06-14 11:39:52 +02005712 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005713 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005714 char *tmp;
5715
Willy Tarreau3842f002009-06-14 11:39:52 +02005716 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005717 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005718 for (arg=0; *args[arg+1]; arg++)
5719 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005720 *tmp = '\0'; // fix the next arg to \0
5721 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005722 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005723 else if (!strcmp(args[0], "default")) {
5724 kwm = KWM_DEF;
5725 for (arg=0; *args[arg+1]; arg++)
5726 args[arg] = args[arg+1]; // shift args after inversion
5727 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005728
William Lallemand0f99e342011-10-12 17:50:54 +02005729 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5730 strcmp(args[0], "log") != 0) {
5731 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005732 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005733 }
5734
Willy Tarreau977b8e42006-12-29 14:19:17 +01005735 if (!strcmp(args[0], "listen") ||
5736 !strcmp(args[0], "frontend") ||
5737 !strcmp(args[0], "backend") ||
5738 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005739 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005740 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005741 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005742 cursection = strdup(args[0]);
5743 }
5744 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005746 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005747 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005748 }
5749 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005750 confsect = CFG_USERLIST;
5751 free(cursection);
5752 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005753 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005754 else if (!strcmp(args[0], "peers")) {
5755 confsect = CFG_PEERS;
5756 free(cursection);
5757 cursection = strdup(args[0]);
5758 }
5759
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 /* else it's a section keyword */
5761
5762 switch (confsect) {
5763 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 break;
5766 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005767 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005769 case CFG_USERLIST:
5770 err_code |= cfg_parse_users(file, linenum, args, kwm);
5771 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005772 case CFG_PEERS:
5773 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5774 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005776 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005777 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005779
5780 if (err_code & ERR_ABORT)
5781 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005783 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005784 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005786 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005787}
5788
Willy Tarreaubb925012009-07-23 13:36:36 +02005789/*
5790 * Returns the error code, 0 if OK, or any combination of :
5791 * - ERR_ABORT: must abort ASAP
5792 * - ERR_FATAL: we can continue parsing but not start the service
5793 * - ERR_WARN: a warning has been emitted
5794 * - ERR_ALERT: an alert has been emitted
5795 * Only the two first ones can stop processing, the two others are just
5796 * indicators.
5797 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005798int check_config_validity()
5799{
5800 int cfgerr = 0;
5801 struct proxy *curproxy = NULL;
5802 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005803 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005804 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005805 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005806 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005808 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809 /*
5810 * Now, check for the integrity of all that we have collected.
5811 */
5812
5813 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005814 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005815
Willy Tarreau193b8c62012-11-22 00:17:38 +01005816 if (!global.tune.max_http_hdr)
5817 global.tune.max_http_hdr = MAX_HTTP_HDR;
5818
5819 if (!global.tune.cookie_len)
5820 global.tune.cookie_len = CAPTURE_LEN;
5821
5822 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5823
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005824 /* first, we will invert the proxy list order */
5825 curproxy = NULL;
5826 while (proxy) {
5827 struct proxy *next;
5828
5829 next = proxy->next;
5830 proxy->next = curproxy;
5831 curproxy = proxy;
5832 if (!next)
5833 break;
5834 proxy = next;
5835 }
5836
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005838 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005839 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005840 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005841 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005842 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005843 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005844 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005845
Willy Tarreau050536d2012-10-04 08:47:34 +02005846 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005847 /* proxy ID not set, use automatic numbering with first
5848 * spare entry starting with next_pxid.
5849 */
5850 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5851 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5852 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005853 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005854 next_pxid++;
5855
Willy Tarreau55ea7572007-06-17 19:56:27 +02005856
Willy Tarreaubaaee002006-06-26 02:48:02 +02005857 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005858 /* ensure we don't keep listeners uselessly bound */
5859 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860 curproxy = curproxy->next;
5861 continue;
5862 }
5863
Willy Tarreau16a21472012-11-19 12:39:59 +01005864 /* number of processes this proxy is bound to */
5865 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5866
Willy Tarreauff01a212009-03-15 13:46:16 +01005867 switch (curproxy->mode) {
5868 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005869 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005870 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005871 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5872 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005873 cfgerr++;
5874 }
5875
5876 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005877 Warning("config : servers will be ignored for %s '%s'.\n",
5878 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005879 break;
5880
5881 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005882 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005883 break;
5884
5885 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005886 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005887 break;
5888 }
5889
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005890 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005891 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005892 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005893 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5894 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005895 cfgerr++;
5896 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005897#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005898 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005899 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5900 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005901 cfgerr++;
5902 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005903#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005904 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005905 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5906 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005907 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005908 }
5909 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005910 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005911 /* If no LB algo is set in a backend, and we're not in
5912 * transparent mode, dispatch mode nor proxy mode, we
5913 * want to use balance roundrobin by default.
5914 */
5915 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5916 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 }
5918 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005919
Willy Tarreau1620ec32011-08-06 17:05:02 +02005920 if (curproxy->options & PR_O_DISPATCH)
5921 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5922 else if (curproxy->options & PR_O_HTTP_PROXY)
5923 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5924 else if (curproxy->options & PR_O_TRANSP)
5925 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005926
Willy Tarreau1620ec32011-08-06 17:05:02 +02005927 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5928 if (curproxy->options & PR_O_DISABLE404) {
5929 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5930 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5931 err_code |= ERR_WARN;
5932 curproxy->options &= ~PR_O_DISABLE404;
5933 }
5934 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5935 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5936 "send-state", proxy_type_str(curproxy), curproxy->id);
5937 err_code |= ERR_WARN;
5938 curproxy->options &= ~PR_O2_CHK_SNDST;
5939 }
Willy Tarreauef781042010-01-27 11:53:01 +01005940 }
5941
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005942 /* if a default backend was specified, let's find it */
5943 if (curproxy->defbe.name) {
5944 struct proxy *target;
5945
Alex Williams96532db2009-11-01 21:27:13 -05005946 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005947 if (!target) {
5948 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5949 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005950 cfgerr++;
5951 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005952 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5953 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005954 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005955 } else {
5956 free(curproxy->defbe.name);
5957 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005958 /* we force the backend to be present on at least all of
5959 * the frontend's processes.
5960 */
5961 target->bind_proc = curproxy->bind_proc ?
5962 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005963
5964 /* Emit a warning if this proxy also has some servers */
5965 if (curproxy->srv) {
5966 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5967 curproxy->id);
5968 err_code |= ERR_WARN;
5969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 }
5971 }
5972
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005973 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005974 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5975 /* map jump target for ACT_SETBE in req_rep chain */
5976 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005977 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005978 struct proxy *target;
5979
Willy Tarreaua496b602006-12-17 23:15:24 +01005980 if (exp->action != ACT_SETBE)
5981 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005982
Alex Williams96532db2009-11-01 21:27:13 -05005983 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005984 if (!target) {
5985 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5986 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005987 cfgerr++;
5988 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005989 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5990 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005991 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005992 } else {
5993 free((void *)exp->replace);
5994 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005995 /* we force the backend to be present on at least all of
5996 * the frontend's processes.
5997 */
5998 target->bind_proc = curproxy->bind_proc ?
5999 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006000 }
6001 }
6002 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006003
6004 /* find the target proxy for 'use_backend' rules */
6005 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006006 struct proxy *target;
6007
Alex Williams96532db2009-11-01 21:27:13 -05006008 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006009
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006010 if (!target) {
6011 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6012 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006013 cfgerr++;
6014 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006015 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6016 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006017 cfgerr++;
6018 } else {
6019 free((void *)rule->be.name);
6020 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006021 /* we force the backend to be present on at least all of
6022 * the frontend's processes.
6023 */
6024 target->bind_proc = curproxy->bind_proc ?
6025 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006026 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006027 }
6028
6029 /* find the target proxy for 'use_backend' rules */
6030 list_for_each_entry(srule, &curproxy->server_rules, list) {
6031 struct server *target = findserver(curproxy, srule->srv.name);
6032
6033 if (!target) {
6034 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6035 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6036 cfgerr++;
6037 continue;
6038 }
6039 free((void *)srule->srv.name);
6040 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006041 }
6042
Emeric Brunb982a3d2010-01-04 15:45:53 +01006043 /* find the target table for 'stick' rules */
6044 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6045 struct proxy *target;
6046
Emeric Brun1d33b292010-01-04 15:47:17 +01006047 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6048 if (mrule->flags & STK_IS_STORE)
6049 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6050
Emeric Brunb982a3d2010-01-04 15:45:53 +01006051 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006052 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006053 else
6054 target = curproxy;
6055
6056 if (!target) {
6057 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6058 curproxy->id, mrule->table.name);
6059 cfgerr++;
6060 }
6061 else if (target->table.size == 0) {
6062 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6063 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6064 cfgerr++;
6065 }
Willy Tarreau12785782012-04-27 21:37:17 +02006066 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6067 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006068 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6069 cfgerr++;
6070 }
6071 else {
6072 free((void *)mrule->table.name);
6073 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006074 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006075 }
6076 }
6077
6078 /* find the target table for 'store response' rules */
6079 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6080 struct proxy *target;
6081
Emeric Brun1d33b292010-01-04 15:47:17 +01006082 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6083
Emeric Brunb982a3d2010-01-04 15:45:53 +01006084 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006085 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006086 else
6087 target = curproxy;
6088
6089 if (!target) {
6090 Alert("Proxy '%s': unable to find store table '%s'.\n",
6091 curproxy->id, mrule->table.name);
6092 cfgerr++;
6093 }
6094 else if (target->table.size == 0) {
6095 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6096 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6097 cfgerr++;
6098 }
Willy Tarreau12785782012-04-27 21:37:17 +02006099 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6100 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006101 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6102 cfgerr++;
6103 }
6104 else {
6105 free((void *)mrule->table.name);
6106 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006107 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006108 }
6109 }
6110
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006111 /* find the target table for 'tcp-request' layer 4 rules */
6112 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6113 struct proxy *target;
6114
Willy Tarreau56123282010-08-06 19:06:56 +02006115 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006116 continue;
6117
6118 if (trule->act_prm.trk_ctr.table.n)
6119 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6120 else
6121 target = curproxy;
6122
6123 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006124 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6125 curproxy->id, trule->act_prm.trk_ctr.table.n,
6126 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006127 cfgerr++;
6128 }
6129 else if (target->table.size == 0) {
6130 Alert("Proxy '%s': table '%s' used but not configured.\n",
6131 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6132 cfgerr++;
6133 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006134 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6135 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6136 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6137 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6138 cfgerr++;
6139 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006140 else {
6141 free(trule->act_prm.trk_ctr.table.n);
6142 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006143 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006144 * to pass a list of counters to track and allocate them right here using
6145 * stktable_alloc_data_type().
6146 */
6147 }
6148 }
6149
Willy Tarreaud1f96522010-08-03 19:34:32 +02006150 /* find the target table for 'tcp-request' layer 6 rules */
6151 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6152 struct proxy *target;
6153
Willy Tarreau56123282010-08-06 19:06:56 +02006154 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006155 continue;
6156
6157 if (trule->act_prm.trk_ctr.table.n)
6158 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6159 else
6160 target = curproxy;
6161
6162 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006163 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6164 curproxy->id, trule->act_prm.trk_ctr.table.n,
6165 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006166 cfgerr++;
6167 }
6168 else if (target->table.size == 0) {
6169 Alert("Proxy '%s': table '%s' used but not configured.\n",
6170 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6171 cfgerr++;
6172 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006173 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6174 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6175 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6176 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6177 cfgerr++;
6178 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006179 else {
6180 free(trule->act_prm.trk_ctr.table.n);
6181 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006182 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006183 * to pass a list of counters to track and allocate them right here using
6184 * stktable_alloc_data_type().
6185 */
6186 }
6187 }
6188
Emeric Brun32da3c42010-09-23 18:39:19 +02006189 if (curproxy->table.peers.name) {
6190 struct peers *curpeers = peers;
6191
6192 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6193 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6194 free((void *)curproxy->table.peers.name);
6195 curproxy->table.peers.p = peers;
6196 break;
6197 }
6198 }
6199
6200 if (!curpeers) {
6201 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6202 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006203 free((void *)curproxy->table.peers.name);
6204 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006205 cfgerr++;
6206 }
6207 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006208 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6209 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006210 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006211 cfgerr++;
6212 }
6213 }
6214
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006215 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006216 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006217 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6218 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6219 "proxy", curproxy->id);
6220 cfgerr++;
6221 goto out_uri_auth_compat;
6222 }
6223
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006224 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006225 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006226 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006227 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006228
Willy Tarreau95fa4692010-02-01 13:05:50 +01006229 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6230 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006231
6232 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006233 uri_auth_compat_req[i++] = "realm";
6234 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6235 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006236
Willy Tarreau95fa4692010-02-01 13:05:50 +01006237 uri_auth_compat_req[i++] = "unless";
6238 uri_auth_compat_req[i++] = "{";
6239 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6240 uri_auth_compat_req[i++] = "}";
6241 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006242
Willy Tarreauff011f22011-01-06 17:51:27 +01006243 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6244 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006245 cfgerr++;
6246 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006247 }
6248
Willy Tarreauff011f22011-01-06 17:51:27 +01006249 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006250
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006251 if (curproxy->uri_auth->auth_realm) {
6252 free(curproxy->uri_auth->auth_realm);
6253 curproxy->uri_auth->auth_realm = NULL;
6254 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006255
6256 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006257 }
6258out_uri_auth_compat:
6259
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006260 cfgerr += acl_find_targets(curproxy);
6261
Willy Tarreau2738a142006-07-08 17:28:09 +02006262 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006263 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006264 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006265 (!curproxy->timeout.connect ||
6266 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006267 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006268 " | While not properly invalid, you will certainly encounter various problems\n"
6269 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006270 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006271 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006272 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006273 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006274
Willy Tarreau1fa31262007-12-03 00:36:16 +01006275 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6276 * We must still support older configurations, so let's find out whether those
6277 * parameters have been set or must be copied from contimeouts.
6278 */
6279 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006280 if (!curproxy->timeout.tarpit ||
6281 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006282 /* tarpit timeout not set. We search in the following order:
6283 * default.tarpit, curr.connect, default.connect.
6284 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006285 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006286 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006287 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006288 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006289 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006290 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006291 }
6292 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006293 (!curproxy->timeout.queue ||
6294 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006295 /* queue timeout not set. We search in the following order:
6296 * default.queue, curr.connect, default.connect.
6297 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006298 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006299 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006300 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006301 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006302 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006303 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006304 }
6305 }
6306
Willy Tarreau1620ec32011-08-06 17:05:02 +02006307 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006308 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6309 curproxy->check_req = (char *)malloc(curproxy->check_len);
6310 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006311 }
6312
Willy Tarreau193b8c62012-11-22 00:17:38 +01006313 /* ensure that cookie capture length is not too large */
6314 if (curproxy->capture_len >= global.tune.cookie_len) {
6315 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6316 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6317 err_code |= ERR_WARN;
6318 curproxy->capture_len = global.tune.cookie_len - 1;
6319 }
6320
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006321 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006322 if (curproxy->nb_req_cap) {
6323 if (curproxy->mode == PR_MODE_HTTP) {
6324 curproxy->req_cap_pool = create_pool("ptrcap",
6325 curproxy->nb_req_cap * sizeof(char *),
6326 MEM_F_SHARED);
6327 } else {
6328 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6329 proxy_type_str(curproxy), curproxy->id);
6330 err_code |= ERR_WARN;
6331 curproxy->to_log &= ~LW_REQHDR;
6332 curproxy->nb_req_cap = 0;
6333 }
6334 }
6335
6336 if (curproxy->nb_rsp_cap) {
6337 if (curproxy->mode == PR_MODE_HTTP) {
6338 curproxy->rsp_cap_pool = create_pool("ptrcap",
6339 curproxy->nb_rsp_cap * sizeof(char *),
6340 MEM_F_SHARED);
6341 } else {
6342 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6343 proxy_type_str(curproxy), curproxy->id);
6344 err_code |= ERR_WARN;
6345 curproxy->to_log &= ~LW_REQHDR;
6346 curproxy->nb_rsp_cap = 0;
6347 }
6348 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006349
Willy Tarreau196729e2012-05-31 19:30:26 +02006350 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006351 if (!(curproxy->cap & PR_CAP_FE)) {
6352 if (curproxy->logformat_string != default_http_log_format &&
6353 curproxy->logformat_string != default_tcp_log_format &&
6354 curproxy->logformat_string != clf_http_log_format)
6355 free(curproxy->logformat_string);
6356 curproxy->logformat_string = NULL;
6357 }
6358
Willy Tarreau196729e2012-05-31 19:30:26 +02006359 if (curproxy->logformat_string)
6360 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6361
6362 if (curproxy->uniqueid_format_string)
6363 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6364
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 /* first, we will invert the servers list order */
6366 newsrv = NULL;
6367 while (curproxy->srv) {
6368 struct server *next;
6369
6370 next = curproxy->srv->next;
6371 curproxy->srv->next = newsrv;
6372 newsrv = curproxy->srv;
6373 if (!next)
6374 break;
6375 curproxy->srv = next;
6376 }
6377
Willy Tarreaudd701652010-05-25 23:03:02 +02006378 /* assign automatic UIDs to servers which don't have one yet */
6379 next_id = 1;
6380 newsrv = curproxy->srv;
6381 while (newsrv != NULL) {
6382 if (!newsrv->puid) {
6383 /* server ID not set, use automatic numbering with first
6384 * spare entry starting with next_svid.
6385 */
6386 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6387 newsrv->conf.id.key = newsrv->puid = next_id;
6388 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6389 }
6390 next_id++;
6391 newsrv = newsrv->next;
6392 }
6393
Willy Tarreau20697042007-11-15 23:26:18 +01006394 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006395 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006396
Willy Tarreau62c3be22012-01-20 13:12:32 +01006397 /*
6398 * If this server supports a maxconn parameter, it needs a dedicated
6399 * tasks to fill the emptied slots when a connection leaves.
6400 * Also, resolve deferred tracking dependency if needed.
6401 */
6402 newsrv = curproxy->srv;
6403 while (newsrv != NULL) {
6404 if (newsrv->minconn > newsrv->maxconn) {
6405 /* Only 'minconn' was specified, or it was higher than or equal
6406 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6407 * this will avoid further useless expensive computations.
6408 */
6409 newsrv->maxconn = newsrv->minconn;
6410 } else if (newsrv->maxconn && !newsrv->minconn) {
6411 /* minconn was not specified, so we set it to maxconn */
6412 newsrv->minconn = newsrv->maxconn;
6413 }
6414
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006415#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006416 if (newsrv->use_ssl || newsrv->check.use_ssl)
6417 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006418#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006419
Willy Tarreau62c3be22012-01-20 13:12:32 +01006420 if (newsrv->trackit) {
6421 struct proxy *px;
6422 struct server *srv;
6423 char *pname, *sname;
6424
6425 pname = newsrv->trackit;
6426 sname = strrchr(pname, '/');
6427
6428 if (sname)
6429 *sname++ = '\0';
6430 else {
6431 sname = pname;
6432 pname = NULL;
6433 }
6434
6435 if (pname) {
6436 px = findproxy(pname, PR_CAP_BE);
6437 if (!px) {
6438 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6439 proxy_type_str(curproxy), curproxy->id,
6440 newsrv->id, pname);
6441 cfgerr++;
6442 goto next_srv;
6443 }
6444 } else
6445 px = curproxy;
6446
6447 srv = findserver(px, sname);
6448 if (!srv) {
6449 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6450 proxy_type_str(curproxy), curproxy->id,
6451 newsrv->id, sname);
6452 cfgerr++;
6453 goto next_srv;
6454 }
6455
6456 if (!(srv->state & SRV_CHECKED)) {
6457 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6458 "tracking as it does not have checks enabled.\n",
6459 proxy_type_str(curproxy), curproxy->id,
6460 newsrv->id, px->id, srv->id);
6461 cfgerr++;
6462 goto next_srv;
6463 }
6464
6465 if (curproxy != px &&
6466 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6467 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6468 "tracking: disable-on-404 option inconsistency.\n",
6469 proxy_type_str(curproxy), curproxy->id,
6470 newsrv->id, px->id, srv->id);
6471 cfgerr++;
6472 goto next_srv;
6473 }
6474
6475 /* if the other server is forced disabled, we have to do the same here */
6476 if (srv->state & SRV_MAINTAIN) {
6477 newsrv->state |= SRV_MAINTAIN;
6478 newsrv->state &= ~SRV_RUNNING;
6479 newsrv->health = 0;
6480 }
6481
6482 newsrv->track = srv;
6483 newsrv->tracknext = srv->tracknext;
6484 srv->tracknext = newsrv;
6485
6486 free(newsrv->trackit);
6487 newsrv->trackit = NULL;
6488 }
6489 next_srv:
6490 newsrv = newsrv->next;
6491 }
6492
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006493 /* We have to initialize the server lookup mechanism depending
6494 * on what LB algorithm was choosen.
6495 */
6496
6497 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6498 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6499 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006500 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6501 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6502 init_server_map(curproxy);
6503 } else {
6504 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6505 fwrr_init_server_groups(curproxy);
6506 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006507 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006508
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006509 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006510 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6511 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6512 fwlc_init_server_tree(curproxy);
6513 } else {
6514 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6515 fas_init_server_tree(curproxy);
6516 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006517 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006518
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006519 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006520 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6521 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6522 chash_init_server_tree(curproxy);
6523 } else {
6524 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6525 init_server_map(curproxy);
6526 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006527 break;
6528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529
6530 if (curproxy->options & PR_O_LOGASAP)
6531 curproxy->to_log &= ~LW_BYTES;
6532
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006533 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006534 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006535 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6536 proxy_type_str(curproxy), curproxy->id);
6537 err_code |= ERR_WARN;
6538 }
6539
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006540 if (curproxy->mode != PR_MODE_HTTP) {
6541 int optnum;
6542
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006543 if (curproxy->uri_auth) {
6544 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6545 proxy_type_str(curproxy), curproxy->id);
6546 err_code |= ERR_WARN;
6547 curproxy->uri_auth = NULL;
6548 }
6549
Willy Tarreau87cf5142011-08-19 22:57:24 +02006550 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006551 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6552 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6553 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006554 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006555 }
6556
6557 if (curproxy->options & PR_O_ORGTO) {
6558 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6559 "originalto", proxy_type_str(curproxy), curproxy->id);
6560 err_code |= ERR_WARN;
6561 curproxy->options &= ~PR_O_ORGTO;
6562 }
6563
6564 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6565 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6566 (curproxy->cap & cfg_opts[optnum].cap) &&
6567 (curproxy->options & cfg_opts[optnum].val)) {
6568 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6569 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6570 err_code |= ERR_WARN;
6571 curproxy->options &= ~cfg_opts[optnum].val;
6572 }
6573 }
6574
6575 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6576 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6577 (curproxy->cap & cfg_opts2[optnum].cap) &&
6578 (curproxy->options2 & cfg_opts2[optnum].val)) {
6579 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6580 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6581 err_code |= ERR_WARN;
6582 curproxy->options2 &= ~cfg_opts2[optnum].val;
6583 }
6584 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006585
Willy Tarreauefa5f512010-03-30 20:13:29 +02006586#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006587 if (curproxy->conn_src.bind_hdr_occ) {
6588 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006589 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006590 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006591 err_code |= ERR_WARN;
6592 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006593#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006594 }
6595
Willy Tarreaubaaee002006-06-26 02:48:02 +02006596 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006597 * ensure that we're not cross-dressing a TCP server into HTTP.
6598 */
6599 newsrv = curproxy->srv;
6600 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006601 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006602 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6603 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006604 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006605 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006606
Willy Tarreau0cec3312011-10-31 13:49:26 +01006607 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6608 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6609 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6610 err_code |= ERR_WARN;
6611 }
6612
Willy Tarreauefa5f512010-03-30 20:13:29 +02006613#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006614 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6615 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006616 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 +01006617 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006618 err_code |= ERR_WARN;
6619 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006620#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006621 newsrv = newsrv->next;
6622 }
6623
Willy Tarreauc1a21672009-08-16 22:37:44 +02006624 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006625 if (!curproxy->accept)
6626 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006627
Willy Tarreauc1a21672009-08-16 22:37:44 +02006628 if (curproxy->tcp_req.inspect_delay ||
6629 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006630 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006631
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006632 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006633 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006634 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006635 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006636
6637 /* both TCP and HTTP must check switching rules */
6638 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6639 }
6640
6641 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006642 if (curproxy->tcp_req.inspect_delay ||
6643 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6644 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6645
Emeric Brun97679e72010-09-23 17:56:44 +02006646 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6647 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6648
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006649 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006650 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006651 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006652 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006653
6654 /* If the backend does requires RDP cookie persistence, we have to
6655 * enable the corresponding analyser.
6656 */
6657 if (curproxy->options2 & PR_O2_RDPC_PRST)
6658 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6659 }
6660
Emeric Brunc52962f2012-11-15 18:28:02 +01006661#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006662 /* Configure SSL for each bind line.
6663 * Note: if configuration fails at some point, the ->ctx member
6664 * remains NULL so that listeners can later detach.
6665 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006666 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006667 if (!bind_conf->is_ssl) {
6668 if (bind_conf->default_ctx) {
6669 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6670 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6671 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006672 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006673 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006674 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006675 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006676 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006677 cfgerr++;
6678 continue;
6679 }
6680
Emeric Brun4b3091e2012-09-24 15:48:52 +02006681 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006682 Alert("Unable to allocate SSL session cache.\n");
6683 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006684 continue;
6685 }
6686
Emeric Brunfc0421f2012-09-07 17:30:07 +02006687 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006688 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006689 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006690#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006691
Willy Tarreaue6b98942007-10-29 01:09:36 +01006692 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006693 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006694 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006695 if (!listener->luid) {
6696 /* listener ID not set, use automatic numbering with first
6697 * spare entry starting with next_luid.
6698 */
6699 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6700 listener->conf.id.key = listener->luid = next_id;
6701 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006702 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006703 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006704
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006705 /* enable separate counters */
6706 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6707 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006708 if (!listener->name)
6709 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006710 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006711
Willy Tarreaue6b98942007-10-29 01:09:36 +01006712 if (curproxy->options & PR_O_TCP_NOLING)
6713 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006714 if (!listener->maxconn)
6715 listener->maxconn = curproxy->maxconn;
6716 if (!listener->backlog)
6717 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006718 if (!listener->maxaccept)
6719 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6720
6721 /* we want to have an optimal behaviour on single process mode to
6722 * maximize the work at once, but in multi-process we want to keep
6723 * some fairness between processes, so we target half of the max
6724 * number of events to be balanced over all the processes the proxy
6725 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6726 * used to disable the limit.
6727 */
6728 if (listener->maxaccept > 0) {
6729 if (nbproc > 1)
6730 listener->maxaccept = (listener->maxaccept + 1) / 2;
6731 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6732 }
6733
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006734 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006735 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006736 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006737 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006738
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006739 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6740 listener->options |= LI_O_TCP_RULES;
6741
Willy Tarreaude3041d2010-05-31 10:56:17 +02006742 if (curproxy->mon_mask.s_addr)
6743 listener->options |= LI_O_CHK_MONNET;
6744
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006745 /* smart accept mode is automatic in HTTP mode */
6746 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006747 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006748 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6749 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006750 }
6751
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006752 /* Release unused SSL configs */
6753 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6754 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006755 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006756#ifdef USE_OPENSSL
6757 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006758 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006759 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006760 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006761 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006762#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006763 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006764
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006765 /* Check multi-process mode compatibility for the current proxy */
6766 if (global.nbproc > 1) {
6767 int nbproc = 0;
6768 if (curproxy->bind_proc) {
6769 int proc;
6770 for (proc = 0; proc < global.nbproc; proc++) {
6771 if (curproxy->bind_proc & (1 << proc)) {
6772 nbproc++;
6773 }
6774 }
6775 } else {
6776 nbproc = global.nbproc;
6777 }
6778 if (curproxy->table.peers.name) {
6779 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6780 curproxy->id);
6781 cfgerr++;
6782 }
6783 if (nbproc > 1) {
6784 if (curproxy->uri_auth) {
6785 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6786 curproxy->id);
6787 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6788 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6789 curproxy->id);
6790 }
6791 }
6792 if (curproxy->appsession_name) {
6793 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6794 curproxy->id);
6795 }
6796 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6797 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6798 curproxy->id);
6799 }
6800 }
6801 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006802
6803 /* create the task associated with the proxy */
6804 curproxy->task = task_new();
6805 if (curproxy->task) {
6806 curproxy->task->context = curproxy;
6807 curproxy->task->process = manage_proxy;
6808 /* no need to queue, it will be done automatically if some
6809 * listener gets limited.
6810 */
6811 curproxy->task->expire = TICK_ETERNITY;
6812 } else {
6813 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6814 curproxy->id);
6815 cfgerr++;
6816 }
6817
Willy Tarreaubaaee002006-06-26 02:48:02 +02006818 curproxy = curproxy->next;
6819 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006820
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006821 /* Check multi-process mode compatibility */
6822 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006823 if (global.stats_fe && !global.stats_fe->bind_proc) {
6824 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 +01006825 }
6826 }
6827
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006828 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6829 struct auth_users *curuser;
6830 int g;
6831
6832 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6833 unsigned int group_mask = 0;
6834 char *group = NULL;
6835
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006836 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006837 continue;
6838
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006839 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006840
6841 for (g = 0; g < curuserlist->grpcnt; g++)
6842 if (!strcmp(curuserlist->groups[g], group))
6843 break;
6844
6845 if (g == curuserlist->grpcnt) {
6846 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6847 curuserlist->name, group, curuser->user);
6848 err_code |= ERR_ALERT | ERR_FATAL;
6849 goto out;
6850 }
6851
6852 group_mask |= (1 << g);
6853 }
6854
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006855 free(curuser->u.groups);
6856 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006857 }
6858
6859 for (g = 0; g < curuserlist->grpcnt; g++) {
6860 char *user = NULL;
6861
6862 if (!curuserlist->groupusers[g])
6863 continue;
6864
6865 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6866 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6867 if (!strcmp(curuser->user, user))
6868 break;
6869
6870 if (!curuser) {
6871 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6872 curuserlist->name, user, curuserlist->groups[g]);
6873 err_code |= ERR_ALERT | ERR_FATAL;
6874 goto out;
6875 }
6876
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006877 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006878 }
6879
6880 free(curuserlist->groupusers[g]);
6881 }
6882
6883 free(curuserlist->groupusers);
6884
6885#ifdef DEBUG_AUTH
6886 for (g = 0; g < curuserlist->grpcnt; g++) {
6887 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6888
6889 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006890 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006891 fprintf(stderr, " %s", curuser->user);
6892 }
6893
6894 fprintf(stderr, "\n");
6895 }
6896#endif
6897
Willy Tarreaufbb78422011-06-05 15:38:35 +02006898 }
6899
6900 /* automatically compute fullconn if not set. We must not do it in the
6901 * loop above because cross-references are not yet fully resolved.
6902 */
6903 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6904 /* If <fullconn> is not set, let's set it to 10% of the sum of
6905 * the possible incoming frontend's maxconns.
6906 */
6907 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6908 struct proxy *fe;
6909 int total = 0;
6910
6911 /* sum up the number of maxconns of frontends which
6912 * reference this backend at least once or which are
6913 * the same one ('listen').
6914 */
6915 for (fe = proxy; fe; fe = fe->next) {
6916 struct switching_rule *rule;
6917 struct hdr_exp *exp;
6918 int found = 0;
6919
6920 if (!(fe->cap & PR_CAP_FE))
6921 continue;
6922
6923 if (fe == curproxy) /* we're on a "listen" instance */
6924 found = 1;
6925
6926 if (fe->defbe.be == curproxy) /* "default_backend" */
6927 found = 1;
6928
6929 /* check if a "use_backend" rule matches */
6930 if (!found) {
6931 list_for_each_entry(rule, &fe->switching_rules, list) {
6932 if (rule->be.backend == curproxy) {
6933 found = 1;
6934 break;
6935 }
6936 }
6937 }
6938
6939 /* check if a "reqsetbe" rule matches */
6940 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6941 if (exp->action == ACT_SETBE &&
6942 (struct proxy *)exp->replace == curproxy) {
6943 found = 1;
6944 break;
6945 }
6946 }
6947
6948 /* now we've checked all possible ways to reference a backend
6949 * from a frontend.
6950 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006951 if (!found)
6952 continue;
6953 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006954 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006955 /* we have the sum of the maxconns in <total>. We only
6956 * keep 10% of that sum to set the default fullconn, with
6957 * a hard minimum of 1 (to avoid a divide by zero).
6958 */
6959 curproxy->fullconn = (total + 9) / 10;
6960 if (!curproxy->fullconn)
6961 curproxy->fullconn = 1;
6962 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006963 }
6964
Willy Tarreau056f5682010-06-06 15:51:11 +02006965 /* initialize stick-tables on backend capable proxies. This must not
6966 * be done earlier because the data size may be discovered while parsing
6967 * other proxies.
6968 */
6969 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006970 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006971
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006972 /*
6973 * Recount currently required checks.
6974 */
6975
6976 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6977 int optnum;
6978
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006979 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6980 if (curproxy->options & cfg_opts[optnum].val)
6981 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006982
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006983 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6984 if (curproxy->options2 & cfg_opts2[optnum].val)
6985 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006986 }
6987
Willy Tarreau122541c2011-09-07 21:24:49 +02006988 if (peers) {
6989 struct peers *curpeers = peers, **last;
6990 struct peer *p, *pb;
6991
6992 /* Remove all peers sections which don't have a valid listener.
6993 * This can happen when a peers section is never referenced and
6994 * does not contain a local peer.
6995 */
6996 last = &peers;
6997 while (*last) {
6998 curpeers = *last;
6999 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007000 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007001 last = &curpeers->next;
7002 continue;
7003 }
7004
7005 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7006 curpeers->id, localpeer);
7007
7008 p = curpeers->remote;
7009 while (p) {
7010 pb = p->next;
7011 free(p->id);
7012 free(p);
7013 p = pb;
7014 }
7015
7016 /* Destroy and unlink this curpeers section.
7017 * Note: curpeers is backed up into *last.
7018 */
7019 free(curpeers->id);
7020 curpeers = curpeers->next;
7021 free(*last);
7022 *last = curpeers;
7023 }
7024 }
7025
Willy Tarreau34eb6712011-10-24 18:15:04 +02007026 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007027 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007028 MEM_F_SHARED);
7029
Willy Tarreaubb925012009-07-23 13:36:36 +02007030 if (cfgerr > 0)
7031 err_code |= ERR_ALERT | ERR_FATAL;
7032 out:
7033 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007034}
7035
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007036/*
7037 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7038 * parsing sessions.
7039 */
7040void cfg_register_keywords(struct cfg_kw_list *kwl)
7041{
7042 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7043}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007044
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007045/*
7046 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7047 */
7048void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7049{
7050 LIST_DEL(&kwl->list);
7051 LIST_INIT(&kwl->list);
7052}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007053
7054/*
7055 * Local variables:
7056 * c-indent-level: 8
7057 * c-basic-offset: 8
7058 * End:
7059 */