blob: bbf0da2899b799211614b1dfd154b56613043ebd [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 Tarreau8b8fd562013-01-18 11:12:27 +01001558 curpeers->peers_fe->conf.file = strdup(file);
1559 curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001560
1561 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1562
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001563 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1564 if (err_msg && *err_msg) {
1565 indent_msg(&err_msg, 2);
1566 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1567 }
1568 else
1569 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1570 file, linenum, args[0], args[1], args[2]);
1571 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001572 err_code |= ERR_FATAL;
1573 goto out;
1574 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001575
1576 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1577 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1578 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1579 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1580 l->accept = session_accept;
1581 l->handler = process_session;
1582 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1583 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1584 global.maxsock += l->maxconn;
1585 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001586 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001587 else {
1588 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1589 file, linenum, args[0], args[1],
1590 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1591 err_code |= ERR_FATAL;
1592 goto out;
1593 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001594 }
1595 } /* neither "peer" nor "peers" */
1596 else if (*args[0] != 0) {
1597 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1598 err_code |= ERR_ALERT | ERR_FATAL;
1599 goto out;
1600 }
1601
1602out:
1603 return err_code;
1604}
1605
1606
Willy Tarreau3842f002009-06-14 11:39:52 +02001607int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001608{
1609 static struct proxy *curproxy = NULL;
1610 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001611 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001612 int rc;
1613 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001614 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001615 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001616 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001617 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001618 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001619
Willy Tarreau977b8e42006-12-29 14:19:17 +01001620 if (!strcmp(args[0], "listen"))
1621 rc = PR_CAP_LISTEN;
1622 else if (!strcmp(args[0], "frontend"))
1623 rc = PR_CAP_FE | PR_CAP_RS;
1624 else if (!strcmp(args[0], "backend"))
1625 rc = PR_CAP_BE | PR_CAP_RS;
1626 else if (!strcmp(args[0], "ruleset"))
1627 rc = PR_CAP_RS;
1628 else
1629 rc = PR_CAP_NONE;
1630
1631 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 if (!*args[1]) {
1633 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1634 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1635 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001636 err_code |= ERR_ALERT | ERR_ABORT;
1637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001639
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001640 err = invalid_char(args[1]);
1641 if (err) {
1642 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1643 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001644 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001645 }
1646
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001647 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1648 /*
1649 * If there are two proxies with the same name only following
1650 * combinations are allowed:
1651 *
1652 * listen backend frontend ruleset
1653 * listen - - - -
1654 * backend - - OK -
1655 * frontend - OK - -
1656 * ruleset - - - -
1657 */
1658
1659 if (!strcmp(curproxy->id, args[1]) &&
1660 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1661 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001662 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1663 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1664 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001665 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001666 }
1667 }
1668
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1670 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001671 err_code |= ERR_ALERT | ERR_ABORT;
1672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001674
Willy Tarreau97cb7802010-01-03 20:23:58 +01001675 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 curproxy->next = proxy;
1677 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001678 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001679 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001680 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001681 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001682 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683
1684 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001685 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001686 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001687 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001688
Willy Tarreau4348fad2012-09-20 16:48:07 +02001689 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1690
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001691 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1692 if (err_msg && *err_msg) {
1693 indent_msg(&err_msg, 2);
1694 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1695 }
1696 else
1697 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1698 file, linenum, args[0], args[1], args[2]);
1699 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001700 err_code |= ERR_FATAL;
1701 goto out;
1702 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001703
Willy Tarreau4348fad2012-09-20 16:48:07 +02001704 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001705 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 }
1708
1709 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001710 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001711 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001712
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001715 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001716 curproxy->no_options = defproxy.no_options;
1717 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001718 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001719 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001720 curproxy->except_net = defproxy.except_net;
1721 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001722 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001723 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001725 if (defproxy.fwdfor_hdr_len) {
1726 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1727 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1728 }
1729
Willy Tarreaub86db342009-11-30 11:50:16 +01001730 if (defproxy.orgto_hdr_len) {
1731 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1732 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1733 }
1734
Mark Lamourinec2247f02012-01-04 13:02:01 -05001735 if (defproxy.server_id_hdr_len) {
1736 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1737 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1738 }
1739
Willy Tarreau977b8e42006-12-29 14:19:17 +01001740 if (curproxy->cap & PR_CAP_FE) {
1741 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001742 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001743 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001744
1745 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001746 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1747 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001748
1749 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001751
Willy Tarreau977b8e42006-12-29 14:19:17 +01001752 if (curproxy->cap & PR_CAP_BE) {
1753 curproxy->fullconn = defproxy.fullconn;
1754 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001756 if (defproxy.check_req) {
1757 curproxy->check_req = calloc(1, defproxy.check_len);
1758 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1759 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001760 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001762 if (defproxy.expect_str) {
1763 curproxy->expect_str = strdup(defproxy.expect_str);
1764 if (defproxy.expect_regex) {
1765 /* note: this regex is known to be valid */
1766 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1767 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1768 }
1769 }
1770
Willy Tarreau67402132012-05-31 20:40:20 +02001771 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001772 if (defproxy.cookie_name)
1773 curproxy->cookie_name = strdup(defproxy.cookie_name);
1774 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001775 if (defproxy.cookie_domain)
1776 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001777
Willy Tarreau31936852010-10-06 16:59:56 +02001778 if (defproxy.cookie_maxidle)
1779 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1780
1781 if (defproxy.cookie_maxlife)
1782 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1783
Emeric Brun647caf12009-06-30 17:57:00 +02001784 if (defproxy.rdp_cookie_name)
1785 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1786 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1787
Willy Tarreau01732802007-11-01 22:48:15 +01001788 if (defproxy.url_param_name)
1789 curproxy->url_param_name = strdup(defproxy.url_param_name);
1790 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001791
Benoitaffb4812009-03-25 13:02:10 +01001792 if (defproxy.hh_name)
1793 curproxy->hh_name = strdup(defproxy.hh_name);
1794 curproxy->hh_len = defproxy.hh_len;
1795 curproxy->hh_match_domain = defproxy.hh_match_domain;
1796
Willy Tarreauef9a3602012-12-08 22:29:20 +01001797 if (defproxy.conn_src.iface_name)
1798 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1799 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1800 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001801 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001803 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001804 if (defproxy.capture_name)
1805 curproxy->capture_name = strdup(defproxy.capture_name);
1806 curproxy->capture_namelen = defproxy.capture_namelen;
1807 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001809
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001811 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001812 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001813 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001814 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001815 curproxy->uri_auth = defproxy.uri_auth;
1816 curproxy->mon_net = defproxy.mon_net;
1817 curproxy->mon_mask = defproxy.mon_mask;
1818 if (defproxy.monitor_uri)
1819 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1820 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001821 if (defproxy.defbe.name)
1822 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001823
1824 /* get either a pointer to the logformat string or a copy of it */
1825 curproxy->logformat_string = defproxy.logformat_string;
1826 if (curproxy->logformat_string &&
1827 curproxy->logformat_string != default_http_log_format &&
1828 curproxy->logformat_string != default_tcp_log_format &&
1829 curproxy->logformat_string != clf_http_log_format)
1830 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001831 }
1832
1833 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001834 curproxy->timeout.connect = defproxy.timeout.connect;
1835 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001836 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001837 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001838 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001839 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001840 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001841 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001842 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001843 }
1844
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001846
1847 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001848 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001849 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001850 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001851 LIST_INIT(&node->list);
1852 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1853 }
1854
Willy Tarreau196729e2012-05-31 19:30:26 +02001855 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1856 if (curproxy->uniqueid_format_string)
1857 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001858
1859 /* copy default header unique id */
1860 if (defproxy.header_unique_id)
1861 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1862
William Lallemand82fe75c2012-10-23 10:25:10 +02001863 /* default compression options */
1864 if (defproxy.comp != NULL) {
1865 curproxy->comp = calloc(1, sizeof(struct comp));
1866 curproxy->comp->algos = defproxy.comp->algos;
1867 curproxy->comp->types = defproxy.comp->types;
1868 }
1869
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001871 curproxy->conf.used_listener_id = EB_ROOT;
1872 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001873
Willy Tarreau93893792009-07-23 13:19:11 +02001874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875 }
1876 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1877 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001878 /* FIXME-20070101: we should do this too at the end of the
1879 * config parsing to free all default values.
1880 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001881 free(defproxy.check_req);
1882 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001883 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001884 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001885 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001886 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001887 free(defproxy.capture_name);
1888 free(defproxy.monitor_uri);
1889 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001890 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001891 free(defproxy.fwdfor_hdr_name);
1892 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001893 free(defproxy.orgto_hdr_name);
1894 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001895 free(defproxy.server_id_hdr_name);
1896 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001897 free(defproxy.expect_str);
1898 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001899
Willy Tarreau39b06652012-06-01 10:58:06 +02001900 if (defproxy.logformat_string != default_http_log_format &&
1901 defproxy.logformat_string != default_tcp_log_format &&
1902 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001903 free(defproxy.logformat_string);
1904
1905 free(defproxy.uniqueid_format_string);
1906
Willy Tarreaua534fea2008-08-03 12:19:50 +02001907 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001908 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001909
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910 /* we cannot free uri_auth because it might already be used */
1911 init_default_instance();
1912 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001913 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 }
1916 else if (curproxy == NULL) {
1917 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001918 err_code |= ERR_ALERT | ERR_FATAL;
1919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 }
1921
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922
1923 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001925 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001926 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001927 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001928
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 if (curproxy == &defproxy) {
1930 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", 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 Tarreau977b8e42006-12-29 14:19:17 +01001934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936
Emeric Bruned760922010-10-22 17:59:25 +02001937 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001938 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001940 err_code |= ERR_ALERT | ERR_FATAL;
1941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001943
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001944 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001945 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001946
1947 /* NOTE: the following line might create several listeners if there
1948 * are comma-separated IPs or port ranges. So all further processing
1949 * will have to be applied to all listeners created after last_listen.
1950 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001951 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1952 if (err_msg && *err_msg) {
1953 indent_msg(&err_msg, 2);
1954 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1955 }
1956 else
1957 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1958 file, linenum, args[0], args[1]);
1959 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_ALERT | ERR_FATAL;
1961 goto out;
1962 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001963
Willy Tarreau4348fad2012-09-20 16:48:07 +02001964 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1965 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001966 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001967 }
1968
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001969 cur_arg = 2;
1970 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001971 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001972 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001973 char *err;
1974
Willy Tarreau26982662012-09-12 23:17:10 +02001975 kw = bind_find_kw(args[cur_arg]);
1976 if (kw) {
1977 char *err = NULL;
1978 int code;
1979
1980 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001981 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1982 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001983 cur_arg += 1 + kw->skip ;
1984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
1986 }
1987
Willy Tarreau4348fad2012-09-20 16:48:07 +02001988 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001989 err_code |= code;
1990
1991 if (code) {
1992 if (err && *err) {
1993 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001994 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001995 }
1996 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001997 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1998 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001999 if (code & ERR_FATAL) {
2000 free(err);
2001 cur_arg += 1 + kw->skip;
2002 goto out;
2003 }
2004 }
2005 free(err);
2006 cur_arg += 1 + kw->skip;
2007 continue;
2008 }
2009
Willy Tarreau8638f482012-09-18 18:01:17 +02002010 err = NULL;
2011 if (!bind_dumped) {
2012 bind_dump_kws(&err);
2013 indent_msg(&err, 4);
2014 bind_dumped = 1;
2015 }
2016
2017 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2018 file, linenum, args[0], args[1], args[cur_arg],
2019 err ? " Registered keywords :" : "", err ? err : "");
2020 free(err);
2021
Willy Tarreau93893792009-07-23 13:19:11 +02002022 err_code |= ERR_ALERT | ERR_FATAL;
2023 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002024 }
Willy Tarreau93893792009-07-23 13:19:11 +02002025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026 }
2027 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2028 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2029 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2030 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002034 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002035 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002036
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 /* flush useless bits */
2038 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002041 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002042 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002043 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002044
Willy Tarreau1c47f852006-07-09 08:22:27 +02002045 if (!*args[1]) {
2046 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002050 }
2051
Willy Tarreaua534fea2008-08-03 12:19:50 +02002052 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002053 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002054 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002055 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002056 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2057
Willy Tarreau93893792009-07-23 13:19:11 +02002058 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2061 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2062 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2063 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2064 else {
2065 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002066 err_code |= ERR_ALERT | ERR_FATAL;
2067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068 }
2069 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002070 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002071 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002072
2073 if (curproxy == &defproxy) {
2074 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2075 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002076 err_code |= ERR_ALERT | ERR_FATAL;
2077 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002078 }
2079
2080 if (!*args[1]) {
2081 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2082 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002085 }
2086
2087 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002088 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002089
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002090 if (curproxy->uuid <= 0) {
2091 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002092 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002095 }
2096
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002097 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2098 if (node) {
2099 struct proxy *target = container_of(node, struct proxy, conf.id);
2100 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2101 file, linenum, proxy_type_str(curproxy), curproxy->id,
2102 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
2105 }
2106 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002107 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002108 else if (!strcmp(args[0], "description")) {
2109 int i, len=0;
2110 char *d;
2111
Cyril Bonté99ed3272010-01-24 23:29:44 +01002112 if (curproxy == &defproxy) {
2113 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2114 file, linenum, args[0]);
2115 err_code |= ERR_ALERT | ERR_FATAL;
2116 goto out;
2117 }
2118
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002119 if (!*args[1]) {
2120 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2121 file, linenum, args[0]);
2122 return -1;
2123 }
2124
2125 for(i=1; *args[i]; i++)
2126 len += strlen(args[i])+1;
2127
2128 d = (char *)calloc(1, len);
2129 curproxy->desc = d;
2130
2131 d += sprintf(d, "%s", args[1]);
2132 for(i=2; *args[i]; i++)
2133 d += sprintf(d, " %s", args[i]);
2134
2135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002136 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2137 curproxy->state = PR_STSTOPPED;
2138 }
2139 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2140 curproxy->state = PR_STNEW;
2141 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002142 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2143 int cur_arg = 1;
2144 unsigned int set = 0;
2145
2146 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002147 unsigned int low, high;
2148
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002149 if (strcmp(args[cur_arg], "all") == 0) {
2150 set = 0;
2151 break;
2152 }
2153 else if (strcmp(args[cur_arg], "odd") == 0) {
2154 set |= 0x55555555;
2155 }
2156 else if (strcmp(args[cur_arg], "even") == 0) {
2157 set |= 0xAAAAAAAA;
2158 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002159 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002160 char *dash = strchr(args[cur_arg], '-');
2161
2162 low = high = str2uic(args[cur_arg]);
2163 if (dash)
2164 high = str2uic(dash + 1);
2165
2166 if (high < low) {
2167 unsigned int swap = low;
2168 low = high;
2169 high = swap;
2170 }
2171
2172 if (low < 1 || high > 32) {
2173 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002177 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002178
2179 if (high > global.nbproc) {
2180 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2181 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002183 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002184 while (low <= high)
2185 set |= 1 << (low++ - 1);
2186 }
2187 else {
2188 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2189 file, linenum, args[0]);
2190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002192 }
2193 cur_arg++;
2194 }
2195 curproxy->bind_proc = set;
2196 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002197 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002198 if (curproxy == &defproxy) {
2199 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002202 }
2203
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002204 err = invalid_char(args[1]);
2205 if (err) {
2206 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2207 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002208 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002209 }
2210
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002211 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2212 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2213 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002216 }
2217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2219 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220
Willy Tarreau977b8e42006-12-29 14:19:17 +01002221 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002222 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002223
Willy Tarreaubaaee002006-06-26 02:48:02 +02002224 if (*(args[1]) == 0) {
2225 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2226 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002230
Willy Tarreau67402132012-05-31 20:40:20 +02002231 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002232 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002233 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002234 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 curproxy->cookie_name = strdup(args[1]);
2236 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002237
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 cur_arg = 2;
2239 while (*(args[cur_arg])) {
2240 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002241 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 }
2243 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002244 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
2246 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002247 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 }
2249 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002250 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
2252 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002253 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002255 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002256 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002259 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002261 else if (!strcmp(args[cur_arg], "httponly")) {
2262 curproxy->ck_opts |= PR_CK_HTTPONLY;
2263 }
2264 else if (!strcmp(args[cur_arg], "secure")) {
2265 curproxy->ck_opts |= PR_CK_SECURE;
2266 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002267 else if (!strcmp(args[cur_arg], "domain")) {
2268 if (!*args[cur_arg + 1]) {
2269 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2270 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002273 }
2274
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002275 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002276 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002277 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2278 " dots nor does not start with a dot."
2279 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002280 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002281 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002282 }
2283
2284 err = invalid_domainchar(args[cur_arg + 1]);
2285 if (err) {
2286 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2287 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002290 }
2291
Willy Tarreau68a897b2009-12-03 23:28:34 +01002292 if (!curproxy->cookie_domain) {
2293 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2294 } else {
2295 /* one domain was already specified, add another one by
2296 * building the string which will be returned along with
2297 * the cookie.
2298 */
2299 char *new_ptr;
2300 int new_len = strlen(curproxy->cookie_domain) +
2301 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2302 new_ptr = malloc(new_len);
2303 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2304 free(curproxy->cookie_domain);
2305 curproxy->cookie_domain = new_ptr;
2306 }
Willy Tarreau31936852010-10-06 16:59:56 +02002307 cur_arg++;
2308 }
2309 else if (!strcmp(args[cur_arg], "maxidle")) {
2310 unsigned int maxidle;
2311 const char *res;
2312
2313 if (!*args[cur_arg + 1]) {
2314 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2315 file, linenum, args[cur_arg]);
2316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
2318 }
2319
2320 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2321 if (res) {
2322 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2323 file, linenum, *res, args[cur_arg]);
2324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
2326 }
2327 curproxy->cookie_maxidle = maxidle;
2328 cur_arg++;
2329 }
2330 else if (!strcmp(args[cur_arg], "maxlife")) {
2331 unsigned int maxlife;
2332 const char *res;
2333
2334 if (!*args[cur_arg + 1]) {
2335 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2336 file, linenum, args[cur_arg]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
2341 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2342 if (res) {
2343 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2344 file, linenum, *res, args[cur_arg]);
2345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
2347 }
2348 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002349 cur_arg++;
2350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002352 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 +02002353 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 }
2357 cur_arg++;
2358 }
Willy Tarreau67402132012-05-31 20:40:20 +02002359 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2361 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 }
2364
Willy Tarreau67402132012-05-31 20:40:20 +02002365 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2367 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002368 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002370
Willy Tarreau67402132012-05-31 20:40:20 +02002371 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002372 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2373 file, linenum);
2374 err_code |= ERR_ALERT | ERR_FATAL;
2375 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002377 else if (!strcmp(args[0], "persist")) { /* persist */
2378 if (*(args[1]) == 0) {
2379 Alert("parsing [%s:%d] : missing persist method.\n",
2380 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002383 }
2384
2385 if (!strncmp(args[1], "rdp-cookie", 10)) {
2386 curproxy->options2 |= PR_O2_RDPC_PRST;
2387
Emeric Brunb982a3d2010-01-04 15:45:53 +01002388 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002389 const char *beg, *end;
2390
2391 beg = args[1] + 11;
2392 end = strchr(beg, ')');
2393
2394 if (!end || end == beg) {
2395 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2396 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002399 }
2400
2401 free(curproxy->rdp_cookie_name);
2402 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2403 curproxy->rdp_cookie_len = end-beg;
2404 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002405 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002406 free(curproxy->rdp_cookie_name);
2407 curproxy->rdp_cookie_name = strdup("msts");
2408 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2409 }
2410 else { /* syntax */
2411 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2412 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002415 }
2416 }
2417 else {
2418 Alert("parsing [%s:%d] : unknown persist method.\n",
2419 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002422 }
2423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002425 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002427 if (curproxy == &defproxy) {
2428 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
2431 }
2432
Willy Tarreau977b8e42006-12-29 14:19:17 +01002433 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002434 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002435
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002437 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 }
2442 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002443 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 curproxy->appsession_name = strdup(args[1]);
2445 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2446 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002447 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2448 if (err) {
2449 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2450 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002453 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002454 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002455
Willy Tarreau51041c72007-09-09 21:56:53 +02002456 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2457 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002458 err_code |= ERR_ALERT | ERR_ABORT;
2459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002461
2462 cur_arg = 6;
2463 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002464 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2465 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002466 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002467 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002468 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002469 } else if (!strcmp(args[cur_arg], "prefix")) {
2470 curproxy->options2 |= PR_O2_AS_PFX;
2471 } else if (!strcmp(args[cur_arg], "mode")) {
2472 if (!*args[cur_arg + 1]) {
2473 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2474 file, linenum, args[0], args[cur_arg]);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
2479 cur_arg++;
2480 if (!strcmp(args[cur_arg], "query-string")) {
2481 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2482 curproxy->options2 |= PR_O2_AS_M_QS;
2483 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2484 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2485 curproxy->options2 |= PR_O2_AS_M_PP;
2486 } else {
2487 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
2490 }
2491 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002492 cur_arg++;
2493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 } /* Url App Session */
2495 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002496 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002500 if (curproxy == &defproxy) {
2501 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
2504 }
2505
Willy Tarreaubaaee002006-06-26 02:48:02 +02002506 if (*(args[4]) == 0) {
2507 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2508 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002512 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002513 curproxy->capture_name = strdup(args[2]);
2514 curproxy->capture_namelen = strlen(curproxy->capture_name);
2515 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 curproxy->to_log |= LW_COOKIE;
2517 }
2518 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2519 struct cap_hdr *hdr;
2520
2521 if (curproxy == &defproxy) {
2522 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 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525 }
2526
2527 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2528 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2529 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 }
2533
2534 hdr = calloc(sizeof(struct cap_hdr), 1);
2535 hdr->next = curproxy->req_cap;
2536 hdr->name = strdup(args[3]);
2537 hdr->namelen = strlen(args[3]);
2538 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002539 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 hdr->index = curproxy->nb_req_cap++;
2541 curproxy->req_cap = hdr;
2542 curproxy->to_log |= LW_REQHDR;
2543 }
2544 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2545 struct cap_hdr *hdr;
2546
2547 if (curproxy == &defproxy) {
2548 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 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 }
2552
2553 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2554 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2555 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 }
2559 hdr = calloc(sizeof(struct cap_hdr), 1);
2560 hdr->next = curproxy->rsp_cap;
2561 hdr->name = strdup(args[3]);
2562 hdr->namelen = strlen(args[3]);
2563 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002564 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 hdr->index = curproxy->nb_rsp_cap++;
2566 curproxy->rsp_cap = hdr;
2567 curproxy->to_log |= LW_RSPHDR;
2568 }
2569 else {
2570 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2571 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
2575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 if (*(args[1]) == 0) {
2581 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
2586 curproxy->conn_retries = atol(args[1]);
2587 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002588 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002589 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002590
2591 if (curproxy == &defproxy) {
2592 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
2595 }
2596
Willy Tarreau20b0de52012-12-24 15:45:22 +01002597 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2598 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2599 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2600 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2601 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2602 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 +01002603 file, linenum, args[0]);
2604 err_code |= ERR_WARN;
2605 }
2606
Willy Tarreauff011f22011-01-06 17:51:27 +01002607 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002608
Willy Tarreauff011f22011-01-06 17:51:27 +01002609 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002610 err_code |= ERR_ALERT | ERR_ABORT;
2611 goto out;
2612 }
2613
Willy Tarreauff011f22011-01-06 17:51:27 +01002614 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2615 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002616 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002617 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2618 /* set the header name and length into the proxy structure */
2619 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2620 err_code |= ERR_WARN;
2621
2622 if (!*args[1]) {
2623 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2624 file, linenum, args[0]);
2625 err_code |= ERR_ALERT | ERR_FATAL;
2626 goto out;
2627 }
2628
2629 /* set the desired header name */
2630 free(curproxy->server_id_hdr_name);
2631 curproxy->server_id_hdr_name = strdup(args[1]);
2632 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2633 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002634 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002635 if (curproxy == &defproxy) {
2636 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_ALERT | ERR_FATAL;
2638 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002639 }
2640
Willy Tarreauef6494c2010-01-28 17:12:36 +01002641 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002642 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2643 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002646 }
2647
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002648 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2649 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2650 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002651 err_code |= ERR_ALERT | ERR_FATAL;
2652 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002653 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002654
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002655 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002656 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002657 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002658 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002659 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002660
Cyril Bonté99ed3272010-01-24 23:29:44 +01002661 if (curproxy == &defproxy) {
2662 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666
Willy Tarreau4baae242012-12-27 12:00:31 +01002667 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2668 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2669 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002672 }
2673
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002674 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002675 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2676 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002677 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002678 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002679 struct switching_rule *rule;
2680
Willy Tarreaub099aca2008-10-12 17:26:37 +02002681 if (curproxy == &defproxy) {
2682 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002685 }
2686
Willy Tarreau55ea7572007-06-17 19:56:27 +02002687 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002689
2690 if (*(args[1]) == 0) {
2691 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002694 }
2695
Willy Tarreauef6494c2010-01-28 17:12:36 +01002696 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002697 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2698 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002701 }
2702
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002703 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2704 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2705 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002708 }
2709
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002710 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002711
Willy Tarreau55ea7572007-06-17 19:56:27 +02002712 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2713 rule->cond = cond;
2714 rule->be.name = strdup(args[1]);
2715 LIST_INIT(&rule->list);
2716 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2717 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002718 else if (strcmp(args[0], "use-server") == 0) {
2719 struct server_rule *rule;
2720
2721 if (curproxy == &defproxy) {
2722 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
2725 }
2726
2727 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2728 err_code |= ERR_WARN;
2729
2730 if (*(args[1]) == 0) {
2731 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
2734 }
2735
2736 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2737 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2738 file, linenum, args[0]);
2739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
2741 }
2742
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002743 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2744 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2745 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
2748 }
2749
2750 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2751
2752 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2753 rule->cond = cond;
2754 rule->srv.name = strdup(args[1]);
2755 LIST_INIT(&rule->list);
2756 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2757 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2758 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002759 else if ((!strcmp(args[0], "force-persist")) ||
2760 (!strcmp(args[0], "ignore-persist"))) {
2761 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002762
2763 if (curproxy == &defproxy) {
2764 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
2767 }
2768
2769 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2770 err_code |= ERR_WARN;
2771
Willy Tarreauef6494c2010-01-28 17:12:36 +01002772 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002773 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2774 file, linenum, args[0]);
2775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
2777 }
2778
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002779 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2780 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2781 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
2784 }
2785
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002786 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002787
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002788 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002789 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002790 if (!strcmp(args[0], "force-persist")) {
2791 rule->type = PERSIST_TYPE_FORCE;
2792 } else {
2793 rule->type = PERSIST_TYPE_IGNORE;
2794 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002795 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002796 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002797 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002798 else if (!strcmp(args[0], "stick-table")) {
2799 int myidx = 1;
2800
Emeric Brun32da3c42010-09-23 18:39:19 +02002801 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002802 curproxy->table.type = (unsigned int)-1;
2803 while (*args[myidx]) {
2804 const char *err;
2805
2806 if (strcmp(args[myidx], "size") == 0) {
2807 myidx++;
2808 if (!*(args[myidx])) {
2809 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2810 file, linenum, args[myidx-1]);
2811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
2813 }
2814 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2815 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2816 file, linenum, *err, args[myidx-1]);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
2819 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002820 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002821 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002822 else if (strcmp(args[myidx], "peers") == 0) {
2823 myidx++;
2824 if (!*(args[myidx])) {
2825 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2826 file, linenum, args[myidx-1]);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829 }
2830 curproxy->table.peers.name = strdup(args[myidx++]);
2831 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002832 else if (strcmp(args[myidx], "expire") == 0) {
2833 myidx++;
2834 if (!*(args[myidx])) {
2835 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2836 file, linenum, args[myidx-1]);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
2840 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2841 if (err) {
2842 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2843 file, linenum, *err, args[myidx-1]);
2844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
2846 }
2847 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002848 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002849 }
2850 else if (strcmp(args[myidx], "nopurge") == 0) {
2851 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002852 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002853 }
2854 else if (strcmp(args[myidx], "type") == 0) {
2855 myidx++;
2856 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2857 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2858 file, linenum, args[myidx]);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002862 /* myidx already points to next arg */
2863 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002864 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002865 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002866 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002867
2868 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002869 nw = args[myidx];
2870 while (*nw) {
2871 /* the "store" keyword supports a comma-separated list */
2872 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002873 sa = NULL; /* store arg */
2874 while (*nw && *nw != ',') {
2875 if (*nw == '(') {
2876 *nw = 0;
2877 sa = ++nw;
2878 while (*nw != ')') {
2879 if (!*nw) {
2880 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2881 file, linenum, args[0], cw);
2882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
2884 }
2885 nw++;
2886 }
2887 *nw = '\0';
2888 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002889 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002890 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002891 if (*nw)
2892 *nw++ = '\0';
2893 type = stktable_get_data_type(cw);
2894 if (type < 0) {
2895 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2896 file, linenum, args[0], cw);
2897 err_code |= ERR_ALERT | ERR_FATAL;
2898 goto out;
2899 }
Willy Tarreauac782882010-06-20 10:41:54 +02002900
2901 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2902 switch (err) {
2903 case PE_NONE: break;
2904 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002905 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2906 file, linenum, args[0], cw);
2907 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002908 break;
2909
2910 case PE_ARG_MISSING:
2911 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2912 file, linenum, args[0], cw);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915
2916 case PE_ARG_NOT_USED:
2917 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2918 file, linenum, args[0], cw);
2919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
2921
2922 default:
2923 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2924 file, linenum, args[0], cw);
2925 err_code |= ERR_ALERT | ERR_FATAL;
2926 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002927 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002928 }
2929 myidx++;
2930 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002931 else {
2932 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2933 file, linenum, args[myidx]);
2934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002936 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002937 }
2938
2939 if (!curproxy->table.size) {
2940 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2941 file, linenum);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945
2946 if (curproxy->table.type == (unsigned int)-1) {
2947 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2948 file, linenum);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 }
2953 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002954 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002955 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002956 int myidx = 0;
2957 const char *name = NULL;
2958 int flags;
2959
2960 if (curproxy == &defproxy) {
2961 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965
2966 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2967 err_code |= ERR_WARN;
2968 goto out;
2969 }
2970
2971 myidx++;
2972 if ((strcmp(args[myidx], "store") == 0) ||
2973 (strcmp(args[myidx], "store-request") == 0)) {
2974 myidx++;
2975 flags = STK_IS_STORE;
2976 }
2977 else if (strcmp(args[myidx], "store-response") == 0) {
2978 myidx++;
2979 flags = STK_IS_STORE | STK_ON_RSP;
2980 }
2981 else if (strcmp(args[myidx], "match") == 0) {
2982 myidx++;
2983 flags = STK_IS_MATCH;
2984 }
2985 else if (strcmp(args[myidx], "on") == 0) {
2986 myidx++;
2987 flags = STK_IS_MATCH | STK_IS_STORE;
2988 }
2989 else {
2990 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
2993 }
2994
2995 if (*(args[myidx]) == 0) {
2996 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
2999 }
3000
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003001 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003002 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003003 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007
3008 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003009 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003010 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3011 file, linenum, args[0], expr->fetch->kw);
3012 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003013 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003014 goto out;
3015 }
3016 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003017 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003018 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3019 file, linenum, args[0], expr->fetch->kw);
3020 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003021 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003022 goto out;
3023 }
3024 }
3025
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003026 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3027 if (expr->fetch->cap & SMP_CAP_L7)
3028 curproxy->acl_requires |= ACL_USE_L7_ANY;
3029
Emeric Brunb982a3d2010-01-04 15:45:53 +01003030 if (strcmp(args[myidx], "table") == 0) {
3031 myidx++;
3032 name = args[myidx++];
3033 }
3034
Willy Tarreauef6494c2010-01-28 17:12:36 +01003035 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003036 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3037 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3038 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003039 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003040 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003041 goto out;
3042 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003043 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003044 else if (*(args[myidx])) {
3045 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3046 file, linenum, args[0], args[myidx]);
3047 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003048 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003049 goto out;
3050 }
Emeric Brun97679e72010-09-23 17:56:44 +02003051 if (flags & STK_ON_RSP)
3052 err_code |= warnif_cond_requires_req(cond, file, linenum);
3053 else
3054 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003055
Emeric Brunb982a3d2010-01-04 15:45:53 +01003056 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3057 rule->cond = cond;
3058 rule->expr = expr;
3059 rule->flags = flags;
3060 rule->table.name = name ? strdup(name) : NULL;
3061 LIST_INIT(&rule->list);
3062 if (flags & STK_ON_RSP)
3063 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3064 else
3065 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3066 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003068 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003069 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003070
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3072 curproxy->uri_auth = NULL; /* we must detach from the default config */
3073
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003074 if (!*args[1]) {
3075 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003076 } else if (!strcmp(args[1], "admin")) {
3077 struct stats_admin_rule *rule;
3078
3079 if (curproxy == &defproxy) {
3080 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
3083 }
3084
3085 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3086 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3087 err_code |= ERR_ALERT | ERR_ABORT;
3088 goto out;
3089 }
3090
3091 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3092 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3093 file, linenum, args[0], args[1]);
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003097 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3098 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3099 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103
3104 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3105
3106 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3107 rule->cond = cond;
3108 LIST_INIT(&rule->list);
3109 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 } else if (!strcmp(args[1], "uri")) {
3111 if (*(args[2]) == 0) {
3112 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3116 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003117 err_code |= ERR_ALERT | ERR_ABORT;
3118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 }
3120 } else if (!strcmp(args[1], "realm")) {
3121 if (*(args[2]) == 0) {
3122 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_ABORT;
3128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003130 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003131 unsigned interval;
3132
3133 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3134 if (err) {
3135 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3136 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003139 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3140 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_ALERT | ERR_ABORT;
3142 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003143 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003144 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003145 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003146
3147 if (curproxy == &defproxy) {
3148 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
3151 }
3152
3153 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3154 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3155 err_code |= ERR_ALERT | ERR_ABORT;
3156 goto out;
3157 }
3158
Willy Tarreauff011f22011-01-06 17:51:27 +01003159 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3160 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003161 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3162 file, linenum, args[0]);
3163 err_code |= ERR_WARN;
3164 }
3165
Willy Tarreauff011f22011-01-06 17:51:27 +01003166 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003167
Willy Tarreauff011f22011-01-06 17:51:27 +01003168 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003169 err_code |= ERR_ALERT | ERR_ABORT;
3170 goto out;
3171 }
3172
Willy Tarreauff011f22011-01-06 17:51:27 +01003173 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3174 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003175
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 } else if (!strcmp(args[1], "auth")) {
3177 if (*(args[2]) == 0) {
3178 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3182 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003183 err_code |= ERR_ALERT | ERR_ABORT;
3184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003185 }
3186 } else if (!strcmp(args[1], "scope")) {
3187 if (*(args[2]) == 0) {
3188 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3192 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_ALERT | ERR_ABORT;
3194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
3196 } else if (!strcmp(args[1], "enable")) {
3197 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3198 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_ABORT;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003202 } else if (!strcmp(args[1], "hide-version")) {
3203 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3204 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_ABORT;
3206 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003207 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003208 } else if (!strcmp(args[1], "show-legends")) {
3209 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3210 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3211 err_code |= ERR_ALERT | ERR_ABORT;
3212 goto out;
3213 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003214 } else if (!strcmp(args[1], "show-node")) {
3215
3216 if (*args[2]) {
3217 int i;
3218 char c;
3219
3220 for (i=0; args[2][i]; i++) {
3221 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003222 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3223 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003224 break;
3225 }
3226
3227 if (!i || args[2][i]) {
3228 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3229 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3230 file, linenum, args[0], args[1]);
3231 err_code |= ERR_ALERT | ERR_FATAL;
3232 goto out;
3233 }
3234 }
3235
3236 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3237 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3238 err_code |= ERR_ALERT | ERR_ABORT;
3239 goto out;
3240 }
3241 } else if (!strcmp(args[1], "show-desc")) {
3242 char *desc = NULL;
3243
3244 if (*args[2]) {
3245 int i, len=0;
3246 char *d;
3247
3248 for(i=2; *args[i]; i++)
3249 len += strlen(args[i])+1;
3250
3251 desc = d = (char *)calloc(1, len);
3252
3253 d += sprintf(d, "%s", args[2]);
3254 for(i=3; *args[i]; i++)
3255 d += sprintf(d, " %s", args[i]);
3256 }
3257
3258 if (!*args[2] && !global.desc)
3259 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3260 file, linenum, args[1]);
3261 else {
3262 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3263 free(desc);
3264 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3265 err_code |= ERR_ALERT | ERR_ABORT;
3266 goto out;
3267 }
3268 free(desc);
3269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003271stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003272 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 +01003273 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
3277 }
3278 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003279 int optnum;
3280
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003281 if (*(args[1]) == '\0') {
3282 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3283 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003287
3288 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3289 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003290 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3291 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3292 file, linenum, cfg_opts[optnum].name);
3293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
3295 }
Willy Tarreau93893792009-07-23 13:19:11 +02003296 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3297 err_code |= ERR_WARN;
3298 goto out;
3299 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003300
Willy Tarreau3842f002009-06-14 11:39:52 +02003301 curproxy->no_options &= ~cfg_opts[optnum].val;
3302 curproxy->options &= ~cfg_opts[optnum].val;
3303
3304 switch (kwm) {
3305 case KWM_STD:
3306 curproxy->options |= cfg_opts[optnum].val;
3307 break;
3308 case KWM_NO:
3309 curproxy->no_options |= cfg_opts[optnum].val;
3310 break;
3311 case KWM_DEF: /* already cleared */
3312 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003313 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003314
Willy Tarreau93893792009-07-23 13:19:11 +02003315 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003316 }
3317 }
3318
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003319 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3320 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003321 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3322 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3323 file, linenum, cfg_opts2[optnum].name);
3324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
3326 }
Willy Tarreau93893792009-07-23 13:19:11 +02003327 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3328 err_code |= ERR_WARN;
3329 goto out;
3330 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003331
Willy Tarreau3842f002009-06-14 11:39:52 +02003332 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3333 curproxy->options2 &= ~cfg_opts2[optnum].val;
3334
3335 switch (kwm) {
3336 case KWM_STD:
3337 curproxy->options2 |= cfg_opts2[optnum].val;
3338 break;
3339 case KWM_NO:
3340 curproxy->no_options2 |= cfg_opts2[optnum].val;
3341 break;
3342 case KWM_DEF: /* already cleared */
3343 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003344 }
Willy Tarreau93893792009-07-23 13:19:11 +02003345 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003346 }
3347 }
3348
Willy Tarreau3842f002009-06-14 11:39:52 +02003349 if (kwm != KWM_STD) {
3350 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003351 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003354 }
3355
Emeric Brun3a058f32009-06-30 18:26:00 +02003356 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003357 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003359 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003360 if (*(args[2]) != '\0') {
3361 if (!strcmp(args[2], "clf")) {
3362 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003363 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003364 } else {
3365 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003368 }
3369 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003370 if (curproxy->logformat_string != default_http_log_format &&
3371 curproxy->logformat_string != default_tcp_log_format &&
3372 curproxy->logformat_string != clf_http_log_format)
3373 free(curproxy->logformat_string);
3374 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003375 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003376 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003378 if (curproxy->logformat_string != default_http_log_format &&
3379 curproxy->logformat_string != default_tcp_log_format &&
3380 curproxy->logformat_string != clf_http_log_format)
3381 free(curproxy->logformat_string);
3382 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 else if (!strcmp(args[1], "tcpka")) {
3385 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003386 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003388
3389 if (curproxy->cap & PR_CAP_FE)
3390 curproxy->options |= PR_O_TCP_CLI_KA;
3391 if (curproxy->cap & PR_CAP_BE)
3392 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }
3394 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003395 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_WARN;
3397
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003399 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003400 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003401 curproxy->options2 &= ~PR_O2_CHK_ANY;
3402 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 if (!*args[2]) { /* no argument */
3404 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3405 curproxy->check_len = strlen(DEF_CHECK_REQ);
3406 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003407 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 curproxy->check_req = (char *)malloc(reqlen);
3409 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003410 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003412 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 if (*args[4])
3414 reqlen += strlen(args[4]);
3415 else
3416 reqlen += strlen("HTTP/1.0");
3417
3418 curproxy->check_req = (char *)malloc(reqlen);
3419 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003420 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003422 }
3423 else if (!strcmp(args[1], "ssl-hello-chk")) {
3424 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003425 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003427
Willy Tarreaua534fea2008-08-03 12:19:50 +02003428 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003429 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003430 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003431 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 }
Willy Tarreau23677902007-05-08 23:50:35 +02003433 else if (!strcmp(args[1], "smtpchk")) {
3434 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003435 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003436 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003437 curproxy->options2 &= ~PR_O2_CHK_ANY;
3438 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003439
3440 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3441 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3442 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3443 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3444 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3445 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3446 curproxy->check_req = (char *)malloc(reqlen);
3447 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3448 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3449 } else {
3450 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3451 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3452 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3453 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3454 }
3455 }
3456 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003457 else if (!strcmp(args[1], "pgsql-check")) {
3458 /* use PostgreSQL request to check servers' health */
3459 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3460 err_code |= ERR_WARN;
3461
3462 free(curproxy->check_req);
3463 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003464 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003465 curproxy->options2 |= PR_O2_PGSQL_CHK;
3466
3467 if (*(args[2])) {
3468 int cur_arg = 2;
3469
3470 while (*(args[cur_arg])) {
3471 if (strcmp(args[cur_arg], "user") == 0) {
3472 char * packet;
3473 uint32_t packet_len;
3474 uint32_t pv;
3475
3476 /* suboption header - needs additional argument for it */
3477 if (*(args[cur_arg+1]) == 0) {
3478 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3479 file, linenum, args[0], args[1], args[cur_arg]);
3480 err_code |= ERR_ALERT | ERR_FATAL;
3481 goto out;
3482 }
3483
3484 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3485 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3486 pv = htonl(0x30000); /* protocol version 3.0 */
3487
3488 packet = (char*) calloc(1, packet_len);
3489
3490 memcpy(packet + 4, &pv, 4);
3491
3492 /* copy "user" */
3493 memcpy(packet + 8, "user", 4);
3494
3495 /* copy username */
3496 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3497
3498 free(curproxy->check_req);
3499 curproxy->check_req = packet;
3500 curproxy->check_len = packet_len;
3501
3502 packet_len = htonl(packet_len);
3503 memcpy(packet, &packet_len, 4);
3504 cur_arg += 2;
3505 } else {
3506 /* unknown suboption - catchall */
3507 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3508 file, linenum, args[0], args[1]);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
3511 }
3512 } /* end while loop */
3513 }
3514 }
3515
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003516 else if (!strcmp(args[1], "redis-check")) {
3517 /* use REDIS PING request to check servers' health */
3518 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3519 err_code |= ERR_WARN;
3520
3521 free(curproxy->check_req);
3522 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003523 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003524 curproxy->options2 |= PR_O2_REDIS_CHK;
3525
3526 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3527 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3528 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3529 }
3530
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003531 else if (!strcmp(args[1], "mysql-check")) {
3532 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003533 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3534 err_code |= ERR_WARN;
3535
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003536 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003537 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003538 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003539 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003540
3541 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3542 * const char mysql40_client_auth_pkt[] = {
3543 * "\x0e\x00\x00" // packet length
3544 * "\x01" // packet number
3545 * "\x00\x00" // client capabilities
3546 * "\x00\x00\x01" // max packet
3547 * "haproxy\x00" // username (null terminated string)
3548 * "\x00" // filler (always 0x00)
3549 * "\x01\x00\x00" // packet length
3550 * "\x00" // packet number
3551 * "\x01" // COM_QUIT command
3552 * };
3553 */
3554
3555 if (*(args[2])) {
3556 int cur_arg = 2;
3557
3558 while (*(args[cur_arg])) {
3559 if (strcmp(args[cur_arg], "user") == 0) {
3560 char *mysqluser;
3561 int packetlen, reqlen, userlen;
3562
3563 /* suboption header - needs additional argument for it */
3564 if (*(args[cur_arg+1]) == 0) {
3565 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3566 file, linenum, args[0], args[1], args[cur_arg]);
3567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
3569 }
3570 mysqluser = args[cur_arg + 1];
3571 userlen = strlen(mysqluser);
3572 packetlen = userlen + 7;
3573 reqlen = packetlen + 9;
3574
3575 free(curproxy->check_req);
3576 curproxy->check_req = (char *)calloc(1, reqlen);
3577 curproxy->check_len = reqlen;
3578
3579 snprintf(curproxy->check_req, 4, "%c%c%c",
3580 ((unsigned char) packetlen & 0xff),
3581 ((unsigned char) (packetlen >> 8) & 0xff),
3582 ((unsigned char) (packetlen >> 16) & 0xff));
3583
3584 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003585 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003586 curproxy->check_req[8] = 1;
3587 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3588 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3589 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3590 cur_arg += 2;
3591 } else {
3592 /* unknown suboption - catchall */
3593 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3594 file, linenum, args[0], args[1]);
3595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
3597 }
3598 } /* end while loop */
3599 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003600 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003601 else if (!strcmp(args[1], "ldap-check")) {
3602 /* use LDAP request to check servers' health */
3603 free(curproxy->check_req);
3604 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003605 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003606 curproxy->options2 |= PR_O2_LDAP_CHK;
3607
3608 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3609 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3610 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3611 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003612 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003613 int cur_arg;
3614
3615 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3616 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003617 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003618
Willy Tarreau87cf5142011-08-19 22:57:24 +02003619 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003620
3621 free(curproxy->fwdfor_hdr_name);
3622 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3623 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3624
3625 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3626 cur_arg = 2;
3627 while (*(args[cur_arg])) {
3628 if (!strcmp(args[cur_arg], "except")) {
3629 /* suboption except - needs additional argument for it */
3630 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3631 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3632 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003635 }
3636 /* flush useless bits */
3637 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003638 cur_arg += 2;
3639 } else if (!strcmp(args[cur_arg], "header")) {
3640 /* suboption header - needs additional argument for it */
3641 if (*(args[cur_arg+1]) == 0) {
3642 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3643 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003644 err_code |= ERR_ALERT | ERR_FATAL;
3645 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003646 }
3647 free(curproxy->fwdfor_hdr_name);
3648 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3649 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3650 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003651 } else if (!strcmp(args[cur_arg], "if-none")) {
3652 curproxy->options &= ~PR_O_FF_ALWAYS;
3653 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003654 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003655 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003656 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003657 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003660 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003661 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003662 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003663 else if (!strcmp(args[1], "originalto")) {
3664 int cur_arg;
3665
3666 /* insert x-original-to field, but not for the IP address listed as an except.
3667 * set default options (ie: bitfield, header name, etc)
3668 */
3669
3670 curproxy->options |= PR_O_ORGTO;
3671
3672 free(curproxy->orgto_hdr_name);
3673 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3674 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3675
Willy Tarreau87cf5142011-08-19 22:57:24 +02003676 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003677 cur_arg = 2;
3678 while (*(args[cur_arg])) {
3679 if (!strcmp(args[cur_arg], "except")) {
3680 /* suboption except - needs additional argument for it */
3681 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3682 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3683 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003686 }
3687 /* flush useless bits */
3688 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3689 cur_arg += 2;
3690 } else if (!strcmp(args[cur_arg], "header")) {
3691 /* suboption header - needs additional argument for it */
3692 if (*(args[cur_arg+1]) == 0) {
3693 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3694 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003697 }
3698 free(curproxy->orgto_hdr_name);
3699 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3700 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3701 cur_arg += 2;
3702 } else {
3703 /* unknown suboption - catchall */
3704 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3705 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003708 }
3709 } /* end while loop */
3710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 else {
3712 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 }
Willy Tarreau93893792009-07-23 13:19:11 +02003716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003718 else if (!strcmp(args[0], "default_backend")) {
3719 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003720 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003721
3722 if (*(args[1]) == 0) {
3723 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003726 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003727 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003728 curproxy->defbe.name = strdup(args[1]);
3729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003731 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003733
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003734 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3735 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 /* enable reconnections to dispatch */
3738 curproxy->options |= PR_O_REDISP;
3739 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003740 else if (!strcmp(args[0], "http-check")) {
3741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003742 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003743
3744 if (strcmp(args[1], "disable-on-404") == 0) {
3745 /* enable a graceful server shutdown on an HTTP 404 response */
3746 curproxy->options |= PR_O_DISABLE404;
3747 }
Willy Tarreauef781042010-01-27 11:53:01 +01003748 else if (strcmp(args[1], "send-state") == 0) {
3749 /* enable emission of the apparent state of a server in HTTP checks */
3750 curproxy->options2 |= PR_O2_CHK_SNDST;
3751 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003752 else if (strcmp(args[1], "expect") == 0) {
3753 const char *ptr_arg;
3754 int cur_arg;
3755
3756 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3757 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
3760 }
3761
3762 cur_arg = 2;
3763 /* consider exclamation marks, sole or at the beginning of a word */
3764 while (*(ptr_arg = args[cur_arg])) {
3765 while (*ptr_arg == '!') {
3766 curproxy->options2 ^= PR_O2_EXP_INV;
3767 ptr_arg++;
3768 }
3769 if (*ptr_arg)
3770 break;
3771 cur_arg++;
3772 }
3773 /* now ptr_arg points to the beginning of a word past any possible
3774 * exclamation mark, and cur_arg is the argument which holds this word.
3775 */
3776 if (strcmp(ptr_arg, "status") == 0) {
3777 if (!*(args[cur_arg + 1])) {
3778 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3779 file, linenum, args[0], args[1], ptr_arg);
3780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
3782 }
3783 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003784 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003785 curproxy->expect_str = strdup(args[cur_arg + 1]);
3786 }
3787 else if (strcmp(ptr_arg, "string") == 0) {
3788 if (!*(args[cur_arg + 1])) {
3789 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3790 file, linenum, args[0], args[1], ptr_arg);
3791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
3793 }
3794 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003795 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003796 curproxy->expect_str = strdup(args[cur_arg + 1]);
3797 }
3798 else if (strcmp(ptr_arg, "rstatus") == 0) {
3799 if (!*(args[cur_arg + 1])) {
3800 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3801 file, linenum, args[0], args[1], ptr_arg);
3802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
3804 }
3805 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003806 free(curproxy->expect_str);
3807 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3808 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003809 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3810 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3811 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3812 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
3815 }
3816 }
3817 else if (strcmp(ptr_arg, "rstring") == 0) {
3818 if (!*(args[cur_arg + 1])) {
3819 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3820 file, linenum, args[0], args[1], ptr_arg);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003825 free(curproxy->expect_str);
3826 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3827 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003828 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3829 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3830 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3831 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835 }
3836 else {
3837 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3838 file, linenum, args[0], args[1], ptr_arg);
3839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
3842 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003843 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003844 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 +02003845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003847 }
3848 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003849 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003850 if (curproxy == &defproxy) {
3851 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003854 }
3855
Willy Tarreaub80c2302007-11-30 20:51:32 +01003856 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003858
3859 if (strcmp(args[1], "fail") == 0) {
3860 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003861 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003862 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3863 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003866 }
3867
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003868 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3869 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3870 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003873 }
3874 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3875 }
3876 else {
3877 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003880 }
3881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882#ifdef TPROXY
3883 else if (!strcmp(args[0], "transparent")) {
3884 /* enable transparent proxy connections */
3885 curproxy->options |= PR_O_TRANSP;
3886 }
3887#endif
3888 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003889 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003891
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892 if (*(args[1]) == 0) {
3893 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 }
3897 curproxy->maxconn = atol(args[1]);
3898 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003899 else if (!strcmp(args[0], "backlog")) { /* backlog */
3900 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003902
3903 if (*(args[1]) == 0) {
3904 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003907 }
3908 curproxy->backlog = atol(args[1]);
3909 }
Willy Tarreau86034312006-12-29 00:10:33 +01003910 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003911 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003912 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003913
Willy Tarreau86034312006-12-29 00:10:33 +01003914 if (*(args[1]) == 0) {
3915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003918 }
3919 curproxy->fullconn = atol(args[1]);
3920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3922 if (*(args[1]) == 0) {
3923 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003927 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3928 if (err) {
3929 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3930 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003933 }
3934 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935 }
3936 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003937 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 if (curproxy == &defproxy) {
3939 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003943 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003945
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 if (strchr(args[1], ':') == NULL) {
3947 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003951 sk = str2sa(args[1]);
3952 if (!sk) {
3953 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
3956 }
3957 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003958 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
3960 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003961 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003962 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003963
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003964 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3965 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003970 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3971 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3972 err_code |= ERR_WARN;
3973
3974 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3975 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3976 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3977 }
3978 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3979 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3980 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3981 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003982 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3983 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3984 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3985 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003986 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003987 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
3990 }
3991 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003992 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003994 char *rport, *raddr;
3995 short realport = 0;
3996 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003998 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003999 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", 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 Tarreau977b8e42006-12-29 14:19:17 +01004003 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004004 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005
4006 if (!*args[2]) {
4007 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4008 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004012
4013 err = invalid_char(args[1]);
4014 if (err) {
4015 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4016 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004019 }
4020
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004021 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004022 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004023
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004024 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4025 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4026 err_code |= ERR_ALERT | ERR_ABORT;
4027 goto out;
4028 }
4029
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004030 /* the servers are linked backwards first */
4031 newsrv->next = curproxy->srv;
4032 curproxy->srv = newsrv;
4033 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004034 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004035 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004037 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004038 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004039 LIST_INIT(&newsrv->pendconns);
4040 do_check = 0;
4041 newsrv->state = SRV_RUNNING; /* early server setup */
4042 newsrv->last_change = now.tv_sec;
4043 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004045 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004046 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004047 * - IP: => port=+0, relative
4048 * - IP:N => port=N, absolute
4049 * - IP:+N => port=+N, relative
4050 * - IP:-N => port=-N, relative
4051 */
4052 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004053 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004054 if (rport) {
4055 *rport++ = 0;
4056 realport = atol(rport);
4057 if (!isdigit((unsigned char)*rport))
4058 newsrv->state |= SRV_MAPPORTS;
4059 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004061
Willy Tarreaufab5a432011-03-04 15:31:53 +01004062 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004063 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004064 if (!sk) {
4065 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004070 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4071 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004072
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004073 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004074 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4075 file, linenum, newsrv->addr.ss_family, args[2]);
4076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
4078 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004079 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004080
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004081 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004082 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004083 newsrv->inter = curproxy->defsrv.inter;
4084 newsrv->fastinter = curproxy->defsrv.fastinter;
4085 newsrv->downinter = curproxy->defsrv.downinter;
4086 newsrv->rise = curproxy->defsrv.rise;
4087 newsrv->fall = curproxy->defsrv.fall;
4088 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4089 newsrv->minconn = curproxy->defsrv.minconn;
4090 newsrv->maxconn = curproxy->defsrv.maxconn;
4091 newsrv->slowstart = curproxy->defsrv.slowstart;
4092 newsrv->onerror = curproxy->defsrv.onerror;
4093 newsrv->consecutive_errors_limit
4094 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004095#ifdef OPENSSL
4096 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4097#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004098 newsrv->uweight = newsrv->iweight
4099 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004101 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004102
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004103 cur_arg = 3;
4104 } else {
4105 newsrv = &curproxy->defsrv;
4106 cur_arg = 1;
4107 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004108
Willy Tarreaubaaee002006-06-26 02:48:02 +02004109 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004110 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004111 newsrv->cookie = strdup(args[cur_arg + 1]);
4112 newsrv->cklen = strlen(args[cur_arg + 1]);
4113 cur_arg += 2;
4114 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004115 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004116 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4117 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4118 cur_arg += 2;
4119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004121 if (!*args[cur_arg + 1]) {
4122 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4123 file, linenum, args[cur_arg]);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
4126 }
4127
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004129 if (newsrv->rise <= 0) {
4130 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4131 file, linenum, args[cur_arg]);
4132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
4134 }
4135
Willy Tarreau96839092010-03-29 10:02:24 +02004136 if (newsrv->health)
4137 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 cur_arg += 2;
4139 }
4140 else if (!strcmp(args[cur_arg], "fall")) {
4141 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004142
4143 if (!*args[cur_arg + 1]) {
4144 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4145 file, linenum, args[cur_arg]);
4146 err_code |= ERR_ALERT | ERR_FATAL;
4147 goto out;
4148 }
4149
4150 if (newsrv->fall <= 0) {
4151 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4152 file, linenum, args[cur_arg]);
4153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
4155 }
4156
Willy Tarreaubaaee002006-06-26 02:48:02 +02004157 cur_arg += 2;
4158 }
4159 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004160 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4161 if (err) {
4162 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4163 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004166 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004167 if (val <= 0) {
4168 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4169 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004172 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004173 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004174 cur_arg += 2;
4175 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004176 else if (!strcmp(args[cur_arg], "fastinter")) {
4177 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4178 if (err) {
4179 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4180 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004183 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004184 if (val <= 0) {
4185 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4186 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004189 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004190 newsrv->fastinter = val;
4191 cur_arg += 2;
4192 }
4193 else if (!strcmp(args[cur_arg], "downinter")) {
4194 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4195 if (err) {
4196 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4197 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004200 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004201 if (val <= 0) {
4202 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4203 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004204 err_code |= ERR_ALERT | ERR_FATAL;
4205 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004206 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004207 newsrv->downinter = val;
4208 cur_arg += 2;
4209 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004210 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004211 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004212 if (!sk) {
4213 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
4216 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004217 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004218 cur_arg += 2;
4219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004220 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004221 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004222 cur_arg += 2;
4223 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004224 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 newsrv->state |= SRV_BACKUP;
4226 cur_arg ++;
4227 }
Simon Hormanfa461682011-06-25 09:39:49 +09004228 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4229 newsrv->state |= SRV_NON_STICK;
4230 cur_arg ++;
4231 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004232 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4233 newsrv->state |= SRV_SEND_PROXY;
4234 cur_arg ++;
4235 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004236 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4237 newsrv->check.send_proxy = 1;
4238 cur_arg ++;
4239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004240 else if (!strcmp(args[cur_arg], "weight")) {
4241 int w;
4242 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004243 if (w < 0 || w > 256) {
4244 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004245 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004248 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004249 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 cur_arg += 2;
4251 }
4252 else if (!strcmp(args[cur_arg], "minconn")) {
4253 newsrv->minconn = atol(args[cur_arg + 1]);
4254 cur_arg += 2;
4255 }
4256 else if (!strcmp(args[cur_arg], "maxconn")) {
4257 newsrv->maxconn = atol(args[cur_arg + 1]);
4258 cur_arg += 2;
4259 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004260 else if (!strcmp(args[cur_arg], "maxqueue")) {
4261 newsrv->maxqueue = atol(args[cur_arg + 1]);
4262 cur_arg += 2;
4263 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004264 else if (!strcmp(args[cur_arg], "slowstart")) {
4265 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004266 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004267 if (err) {
4268 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4269 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004270 err_code |= ERR_ALERT | ERR_FATAL;
4271 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004272 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004273 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004274 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4275 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004278 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004279 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004280 cur_arg += 2;
4281 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004282 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004283
4284 if (!*args[cur_arg + 1]) {
4285 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4286 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004289 }
4290
4291 newsrv->trackit = strdup(args[cur_arg + 1]);
4292
4293 cur_arg += 2;
4294 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004295 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004296 global.maxsock++;
4297 do_check = 1;
4298 cur_arg += 1;
4299 }
Willy Tarreau96839092010-03-29 10:02:24 +02004300 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4301 newsrv->state |= SRV_MAINTAIN;
4302 newsrv->state &= ~SRV_RUNNING;
4303 newsrv->health = 0;
4304 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004305 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004306 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004307 if (!strcmp(args[cur_arg + 1], "none"))
4308 newsrv->observe = HANA_OBS_NONE;
4309 else if (!strcmp(args[cur_arg + 1], "layer4"))
4310 newsrv->observe = HANA_OBS_LAYER4;
4311 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4312 if (curproxy->mode != PR_MODE_HTTP) {
4313 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4314 file, linenum, args[cur_arg + 1]);
4315 err_code |= ERR_ALERT;
4316 }
4317 newsrv->observe = HANA_OBS_LAYER7;
4318 }
4319 else {
4320 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004321 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004322 file, linenum, args[cur_arg], args[cur_arg + 1]);
4323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
4325 }
4326
4327 cur_arg += 2;
4328 }
4329 else if (!strcmp(args[cur_arg], "on-error")) {
4330 if (!strcmp(args[cur_arg + 1], "fastinter"))
4331 newsrv->onerror = HANA_ONERR_FASTINTER;
4332 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4333 newsrv->onerror = HANA_ONERR_FAILCHK;
4334 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4335 newsrv->onerror = HANA_ONERR_SUDDTH;
4336 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4337 newsrv->onerror = HANA_ONERR_MARKDWN;
4338 else {
4339 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004340 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004341 file, linenum, args[cur_arg], args[cur_arg + 1]);
4342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
4344 }
4345
4346 cur_arg += 2;
4347 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004348 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4349 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4350 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4351 else {
4352 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4353 file, linenum, args[cur_arg], args[cur_arg + 1]);
4354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
4356 }
4357
4358 cur_arg += 2;
4359 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004360 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4361 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4362 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4363 else {
4364 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4365 file, linenum, args[cur_arg], args[cur_arg + 1]);
4366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
4368 }
4369
4370 cur_arg += 2;
4371 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004372 else if (!strcmp(args[cur_arg], "error-limit")) {
4373 if (!*args[cur_arg + 1]) {
4374 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4375 file, linenum, args[cur_arg]);
4376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
4378 }
4379
4380 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4381
4382 if (newsrv->consecutive_errors_limit <= 0) {
4383 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4384 file, linenum, args[cur_arg]);
4385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
4387 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004388 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004389 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004390 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004391 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004392 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004393
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004395 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4396 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004400 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004401 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4402 if (!sk) {
4403 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
4406 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004407 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004408
4409 if (port_low != port_high) {
4410 int i;
4411 if (port_low <= 0 || port_low > 65535 ||
4412 port_high <= 0 || port_high > 65535 ||
4413 port_low > port_high) {
4414 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4415 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004418 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004419 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4420 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4421 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004422 }
4423
Willy Tarreaubaaee002006-06-26 02:48:02 +02004424 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004425 while (*(args[cur_arg])) {
4426 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004427#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4428#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004429 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004430 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4431 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004432 err_code |= ERR_ALERT | ERR_FATAL;
4433 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004434 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004435#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004436 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004437 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004438 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004441 }
4442 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004443 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4444 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004445 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004446 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4447 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004448 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4449 char *name, *end;
4450
4451 name = args[cur_arg+1] + 7;
4452 while (isspace(*name))
4453 name++;
4454
4455 end = name;
4456 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4457 end++;
4458
Willy Tarreauef9a3602012-12-08 22:29:20 +01004459 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4460 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4461 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4462 newsrv->conn_src.bind_hdr_len = end - name;
4463 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4464 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4465 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004466
4467 /* now look for an occurrence number */
4468 while (isspace(*end))
4469 end++;
4470 if (*end == ',') {
4471 end++;
4472 name = end;
4473 if (*end == '-')
4474 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004475 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004476 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004477 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004478 }
4479
Willy Tarreauef9a3602012-12-08 22:29:20 +01004480 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004481 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4482 " occurrences values smaller than %d.\n",
4483 file, linenum, MAX_HDR_HISTORY);
4484 err_code |= ERR_ALERT | ERR_FATAL;
4485 goto out;
4486 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004487 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004488 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004489 if (!sk) {
4490 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
4493 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004494 newsrv->conn_src.tproxy_addr = *sk;
4495 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004496 }
4497 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004498#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004499 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004500#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004501 cur_arg += 2;
4502 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004503#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004504 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004505 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004508#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4509 } /* "usesrc" */
4510
4511 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4512#ifdef SO_BINDTODEVICE
4513 if (!*args[cur_arg + 1]) {
4514 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4515 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004518 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004519 free(newsrv->conn_src.iface_name);
4520 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4521 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004522 global.last_checks |= LSTCHK_NETADM;
4523#else
4524 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4525 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004526 err_code |= ERR_ALERT | ERR_FATAL;
4527 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004528#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004529 cur_arg += 2;
4530 continue;
4531 }
4532 /* this keyword in not an option of "source" */
4533 break;
4534 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004535 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004536 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004537 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4538 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004539 err_code |= ERR_ALERT | ERR_FATAL;
4540 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004543 static int srv_dumped;
4544 struct srv_kw *kw;
4545 char *err;
4546
4547 kw = srv_find_kw(args[cur_arg]);
4548 if (kw) {
4549 char *err = NULL;
4550 int code;
4551
4552 if (!kw->parse) {
4553 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4554 file, linenum, args[0], args[1], args[cur_arg]);
4555 cur_arg += 1 + kw->skip ;
4556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
4558 }
4559
4560 if (defsrv && !kw->default_ok) {
4561 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4562 file, linenum, args[0], args[1], args[cur_arg]);
4563 cur_arg += 1 + kw->skip ;
4564 err_code |= ERR_ALERT;
4565 continue;
4566 }
4567
4568 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4569 err_code |= code;
4570
4571 if (code) {
4572 if (err && *err) {
4573 indent_msg(&err, 2);
4574 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4575 }
4576 else
4577 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4578 file, linenum, args[0], args[1], args[cur_arg]);
4579 if (code & ERR_FATAL) {
4580 free(err);
4581 cur_arg += 1 + kw->skip;
4582 goto out;
4583 }
4584 }
4585 free(err);
4586 cur_arg += 1 + kw->skip;
4587 continue;
4588 }
4589
4590 err = NULL;
4591 if (!srv_dumped) {
4592 srv_dump_kws(&err);
4593 indent_msg(&err, 4);
4594 srv_dumped = 1;
4595 }
4596
4597 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4598 file, linenum, args[0], args[1], args[cur_arg],
4599 err ? " Registered keywords :" : "", err ? err : "");
4600 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004601
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004604 }
4605 }
4606
4607 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004608 if (newsrv->trackit) {
4609 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4610 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004613 }
4614
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004615 /* If neither a port nor an addr was specified and no check transport
4616 * layer is forced, then the transport layer used by the checks is the
4617 * same as for the production traffic. Otherwise we use raw_sock by
4618 * default, unless one is specified.
4619 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004620 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004621#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004622 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004623#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004624 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4625 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004626 /* try to get the port from check.addr if check.port not set */
4627 if (!newsrv->check.port)
4628 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004629
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004630 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4631 newsrv->check.port = realport; /* by default */
4632 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004633 /* not yet valid, because no port was set on
4634 * the server either. We'll check if we have
4635 * a known port on the first listener.
4636 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004637 struct listener *l;
4638
4639 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004640 newsrv->check.port = get_host_port(&l->addr);
4641 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004642 break;
4643 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004644 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004645 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004646 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4647 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004651
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004652 /* Allocate buffer for check requests... */
4653 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004654 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4655 err_code |= ERR_ALERT | ERR_ABORT;
4656 goto out;
4657 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004658 newsrv->check.bi->size = global.tune.chksize;
4659
4660 /* Allocate buffer for check responses... */
4661 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4662 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4663 err_code |= ERR_ALERT | ERR_ABORT;
4664 goto out;
4665 }
4666 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004667
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004668 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004669 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004670 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4671 err_code |= ERR_ALERT | ERR_ABORT;
4672 goto out;
4673 }
4674
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004675 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4676 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 newsrv->state |= SRV_CHECKED;
4678 }
4679
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004680 if (!defsrv) {
4681 if (newsrv->state & SRV_BACKUP)
4682 curproxy->srv_bck++;
4683 else
4684 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004685
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004686 newsrv->prev_state = newsrv->state;
4687 }
William Lallemanda73203e2012-03-12 12:48:57 +01004688 }
4689
4690 else if (strcmp(args[0], "unique-id-format") == 0) {
4691 if (!*(args[1])) {
4692 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
4695 }
William Lallemand3203ff42012-11-11 17:30:56 +01004696 if (*(args[2])) {
4697 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
4700 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004701 free(curproxy->uniqueid_format_string);
4702 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004703 }
William Lallemanda73203e2012-03-12 12:48:57 +01004704
4705 else if (strcmp(args[0], "unique-id-header") == 0) {
4706 if (!*(args[1])) {
4707 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
4710 }
4711 free(curproxy->header_unique_id);
4712 curproxy->header_unique_id = strdup(args[1]);
4713 }
4714
William Lallemand723b73a2012-02-08 16:37:49 +01004715 else if (strcmp(args[0], "log-format") == 0) {
4716 if (!*(args[1])) {
4717 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720 }
William Lallemand3203ff42012-11-11 17:30:56 +01004721 if (*(args[2])) {
4722 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4723 err_code |= ERR_ALERT | ERR_FATAL;
4724 goto out;
4725 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004726
4727 if (curproxy->logformat_string != default_http_log_format &&
4728 curproxy->logformat_string != default_tcp_log_format &&
4729 curproxy->logformat_string != clf_http_log_format)
4730 free(curproxy->logformat_string);
4731 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004732 }
William Lallemand723b73a2012-02-08 16:37:49 +01004733
William Lallemand0f99e342011-10-12 17:50:54 +02004734 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4735 /* delete previous herited or defined syslog servers */
4736 struct logsrv *back;
4737
4738 if (*(args[1]) != 0) {
4739 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
4742 }
4743
William Lallemand723b73a2012-02-08 16:37:49 +01004744 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4745 LIST_DEL(&tmplogsrv->list);
4746 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004747 }
4748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004750 struct logsrv *logsrv;
4751
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004753 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004754 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004755 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004756 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004757 LIST_INIT(&node->list);
4758 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 }
4761 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004762
4763 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764
William Lallemand0f99e342011-10-12 17:50:54 +02004765 logsrv->facility = get_log_facility(args[2]);
4766 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004768 err_code |= ERR_ALERT | ERR_FATAL;
4769 goto out;
4770
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 }
4772
William Lallemand0f99e342011-10-12 17:50:54 +02004773 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004774 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004775 logsrv->level = get_log_level(args[3]);
4776 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
4780
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781 }
4782 }
4783
William Lallemand0f99e342011-10-12 17:50:54 +02004784 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004785 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004786 logsrv->minlvl = get_log_level(args[4]);
4787 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004788 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
4791
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004792 }
4793 }
4794
Robert Tsai81ae1952007-12-05 10:47:29 +01004795 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004796 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004797 if (!sk) {
4798 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004799 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802 }
William Lallemand0f99e342011-10-12 17:50:54 +02004803 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004804 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004805 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004806 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004807 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
4810 }
William Lallemand0f99e342011-10-12 17:50:54 +02004811 logsrv->addr = *sk;
4812 if (!get_host_port(&logsrv->addr))
4813 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 }
William Lallemand0f99e342011-10-12 17:50:54 +02004815
4816 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004817 }
4818 else {
4819 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4820 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004823 }
4824 }
4825 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004826 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004827 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004828
Willy Tarreau977b8e42006-12-29 14:19:17 +01004829 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004830 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004831
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004833 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4834 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004837 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004838
4839 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004840 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4841 free(curproxy->conn_src.iface_name);
4842 curproxy->conn_src.iface_name = NULL;
4843 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004844
Willy Tarreaud5191e72010-02-09 20:50:45 +01004845 sk = str2sa(args[1]);
4846 if (!sk) {
4847 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
4850 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004851 curproxy->conn_src.source_addr = *sk;
4852 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004853
4854 cur_arg = 2;
4855 while (*(args[cur_arg])) {
4856 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004857#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4858#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004859 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004860 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4861 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004864 }
4865#endif
4866 if (!*args[cur_arg + 1]) {
4867 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4868 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004871 }
4872
4873 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004874 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4875 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004876 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004877 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4878 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004879 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4880 char *name, *end;
4881
4882 name = args[cur_arg+1] + 7;
4883 while (isspace(*name))
4884 name++;
4885
4886 end = name;
4887 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4888 end++;
4889
Willy Tarreauef9a3602012-12-08 22:29:20 +01004890 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4891 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4892 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4893 curproxy->conn_src.bind_hdr_len = end - name;
4894 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4895 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4896 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004897
4898 /* now look for an occurrence number */
4899 while (isspace(*end))
4900 end++;
4901 if (*end == ',') {
4902 end++;
4903 name = end;
4904 if (*end == '-')
4905 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004906 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004907 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004908 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004909 }
4910
Willy Tarreauef9a3602012-12-08 22:29:20 +01004911 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004912 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4913 " occurrences values smaller than %d.\n",
4914 file, linenum, MAX_HDR_HISTORY);
4915 err_code |= ERR_ALERT | ERR_FATAL;
4916 goto out;
4917 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004918 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004919 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004920 if (!sk) {
4921 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
4924 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004925 curproxy->conn_src.tproxy_addr = *sk;
4926 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004927 }
4928 global.last_checks |= LSTCHK_NETADM;
4929#if !defined(CONFIG_HAP_LINUX_TPROXY)
4930 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004931#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004932#else /* no TPROXY support */
4933 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004934 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004935 err_code |= ERR_ALERT | ERR_FATAL;
4936 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004937#endif
4938 cur_arg += 2;
4939 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004940 }
4941
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004942 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4943#ifdef SO_BINDTODEVICE
4944 if (!*args[cur_arg + 1]) {
4945 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4946 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004947 err_code |= ERR_ALERT | ERR_FATAL;
4948 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004949 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004950 free(curproxy->conn_src.iface_name);
4951 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4952 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004953 global.last_checks |= LSTCHK_NETADM;
4954#else
4955 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4956 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004959#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004960 cur_arg += 2;
4961 continue;
4962 }
4963 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004964 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004967 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004969 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4970 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4971 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004975 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004976 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004977 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4978 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982
4983 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004984 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004985 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004986 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
4989 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004990 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004991 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004992 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004993 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
4996 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004997 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004998 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004999 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005000 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 }
5003 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005004 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005005 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005006 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005007 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 }
5010 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005011 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005012 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005013 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005014 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005017 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005018 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005019 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005020 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005021 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005022 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005023 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005024 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005025 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005026 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005027 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005028 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005029 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005030 }
5031 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005032 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005033 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005034 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005035 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005036 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005039 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5041 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005045
5046 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005047 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005048 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005049 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005051 }
5052 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005053 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005054 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005055 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005056 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005058 }
5059 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005060 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005061 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005062 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005063 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005065 }
5066 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005067 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005068 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005069 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005070 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005072 }
5073 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005074 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005075 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005076 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005077 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005080 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005081 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005082 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005083 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005084 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005085 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005088 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005089
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 if (curproxy == &defproxy) {
5091 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005095 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005096 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 if (*(args[1]) == 0) {
5099 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005103
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005104 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005105 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5106 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5107 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
5110 }
5111 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5112 }
5113 else if (*args[2]) {
5114 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5115 file, linenum, args[0], args[2]);
5116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
5118 }
5119
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005120 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005121 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005122 wl->s = strdup(args[1]);
5123 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005124 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 }
5126 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005127 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5129 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005132 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005133
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005135 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005136 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005137 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 }
5140 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005142 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005143 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005144 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005146 }
5147 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005149 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005150 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 }
5154 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5157 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005158 err_code |= ERR_ALERT | ERR_FATAL;
5159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 }
5161
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005163 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005164 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005165 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 }
5168 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005169 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005170 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005171 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 }
5175 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005177 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005178 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005179 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 }
5182 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005183 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005184
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 if (curproxy == &defproxy) {
5186 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005187 err_code |= ERR_ALERT | ERR_FATAL;
5188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005189 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005190 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 if (*(args[1]) == 0) {
5194 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005197 }
5198
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005199 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005200 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5201 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5202 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
5205 }
5206 err_code |= warnif_cond_requires_req(cond, file, linenum);
5207 }
5208 else if (*args[2]) {
5209 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5210 file, linenum, args[0], args[2]);
5211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
5213 }
5214
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005215 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005216 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005217 wl->s = strdup(args[1]);
5218 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005219 }
5220 else if (!strcmp(args[0], "errorloc") ||
5221 !strcmp(args[0], "errorloc302") ||
5222 !strcmp(args[0], "errorloc303")) { /* error location */
5223 int errnum, errlen;
5224 char *err;
5225
Willy Tarreau977b8e42006-12-29 14:19:17 +01005226 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005228
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005230 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005231 err_code |= ERR_ALERT | ERR_FATAL;
5232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 }
5234
5235 errnum = atol(args[1]);
5236 if (!strcmp(args[0], "errorloc303")) {
5237 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5238 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5239 } else {
5240 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5241 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5242 }
5243
Willy Tarreau0f772532006-12-23 20:51:41 +01005244 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5245 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005246 chunk_destroy(&curproxy->errmsg[rc]);
5247 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005248 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005251
5252 if (rc >= HTTP_ERR_SIZE) {
5253 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5254 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005255 free(err);
5256 }
5257 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005258 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5259 int errnum, errlen, fd;
5260 char *err;
5261 struct stat stat;
5262
5263 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005265
5266 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005267 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005270 }
5271
5272 fd = open(args[2], O_RDONLY);
5273 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5274 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5275 file, linenum, args[2], args[1]);
5276 if (fd >= 0)
5277 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005278 err_code |= ERR_ALERT | ERR_FATAL;
5279 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005280 }
5281
Willy Tarreau27a674e2009-08-17 07:23:33 +02005282 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005283 errlen = stat.st_size;
5284 } else {
5285 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005286 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005287 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005288 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005289 }
5290
5291 err = malloc(errlen); /* malloc() must succeed during parsing */
5292 errnum = read(fd, err, errlen);
5293 if (errnum != errlen) {
5294 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5295 file, linenum, args[2], args[1]);
5296 close(fd);
5297 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005298 err_code |= ERR_ALERT | ERR_FATAL;
5299 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005300 }
5301 close(fd);
5302
5303 errnum = atol(args[1]);
5304 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5305 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005306 chunk_destroy(&curproxy->errmsg[rc]);
5307 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005308 break;
5309 }
5310 }
5311
5312 if (rc >= HTTP_ERR_SIZE) {
5313 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5314 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005315 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005316 free(err);
5317 }
5318 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005319 else if (!strcmp(args[0], "compression")) {
5320 struct comp *comp;
5321 if (curproxy->comp == NULL) {
5322 comp = calloc(1, sizeof(struct comp));
5323 curproxy->comp = comp;
5324 } else {
5325 comp = curproxy->comp;
5326 }
5327
5328 if (!strcmp(args[1], "algo")) {
5329 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005330 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005331
William Lallemand82fe75c2012-10-23 10:25:10 +02005332 cur_arg = 2;
5333 if (!*args[cur_arg]) {
5334 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5335 file, linenum, args[0]);
5336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
5338 }
5339 while (*(args[cur_arg])) {
5340 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5341 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5342 file, linenum, args[0], args[cur_arg]);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
William Lallemand552df672012-11-07 13:21:47 +01005346 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5347 curproxy->comp->algos->end(&ctx);
5348 } else {
5349 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5350 file, linenum, args[0], args[cur_arg]);
5351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
5353 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005354 cur_arg ++;
5355 continue;
5356 }
5357 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005358 else if (!strcmp(args[1], "offload")) {
5359 comp->offload = 1;
5360 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005361 else if (!strcmp(args[1], "type")) {
5362 int cur_arg;
5363 cur_arg = 2;
5364 if (!*args[cur_arg]) {
5365 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5366 file, linenum, args[0]);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 }
5370 while (*(args[cur_arg])) {
5371 comp_append_type(comp, args[cur_arg]);
5372 cur_arg ++;
5373 continue;
5374 }
5375 }
5376 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005377 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005378 file, linenum, args[0]);
5379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
5381 }
5382 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005384 struct cfg_kw_list *kwl;
5385 int index;
5386
5387 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5388 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5389 if (kwl->kw[index].section != CFG_LISTEN)
5390 continue;
5391 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5392 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005393 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005394 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005395 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005398 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005399 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005400 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005401 err_code |= ERR_WARN;
5402 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005403 }
Willy Tarreau93893792009-07-23 13:19:11 +02005404 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005405 }
5406 }
5407 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005408
Willy Tarreau6daf3432008-01-22 16:44:08 +01005409 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 }
Willy Tarreau93893792009-07-23 13:19:11 +02005413 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005414 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005415 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005416}
5417
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005418int
5419cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5420{
5421
5422 int err_code = 0;
5423 const char *err;
5424
5425 if (!strcmp(args[0], "userlist")) { /* new userlist */
5426 struct userlist *newul;
5427
5428 if (!*args[1]) {
5429 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5430 file, linenum, args[0]);
5431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
5433 }
5434
5435 err = invalid_char(args[1]);
5436 if (err) {
5437 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5438 file, linenum, *err, args[0], args[1]);
5439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 }
5442
5443 for (newul = userlist; newul; newul = newul->next)
5444 if (!strcmp(newul->name, args[1])) {
5445 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5446 file, linenum, args[1]);
5447 err_code |= ERR_WARN;
5448 goto out;
5449 }
5450
5451 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5452 if (!newul) {
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->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5459 newul->name = strdup(args[1]);
5460
5461 if (!newul->groupusers | !newul->name) {
5462 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5463 err_code |= ERR_ALERT | ERR_ABORT;
5464 goto out;
5465 }
5466
5467 newul->next = userlist;
5468 userlist = newul;
5469
5470 } else if (!strcmp(args[0], "group")) { /* new group */
5471 int cur_arg, i;
5472 const char *err;
5473
5474 if (!*args[1]) {
5475 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5476 file, linenum, args[0]);
5477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
5480
5481 err = invalid_char(args[1]);
5482 if (err) {
5483 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5484 file, linenum, *err, args[0], args[1]);
5485 err_code |= ERR_ALERT | ERR_FATAL;
5486 goto out;
5487 }
5488
5489 for(i = 0; i < userlist->grpcnt; i++)
5490 if (!strcmp(userlist->groups[i], args[1])) {
5491 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5492 file, linenum, args[1], userlist->name);
5493 err_code |= ERR_ALERT;
5494 goto out;
5495 }
5496
5497 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5498 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5499 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
5503
5504 cur_arg = 2;
5505
5506 while (*args[cur_arg]) {
5507 if (!strcmp(args[cur_arg], "users")) {
5508 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5509 cur_arg += 2;
5510 continue;
5511 } else {
5512 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5513 file, linenum, args[0]);
5514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
5516 }
5517 }
5518
5519 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5520 } else if (!strcmp(args[0], "user")) { /* new user */
5521 struct auth_users *newuser;
5522 int cur_arg;
5523
5524 if (!*args[1]) {
5525 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5526 file, linenum, args[0]);
5527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
5529 }
5530
5531 for (newuser = userlist->users; newuser; newuser = newuser->next)
5532 if (!strcmp(newuser->user, args[1])) {
5533 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5534 file, linenum, args[1], userlist->name);
5535 err_code |= ERR_ALERT;
5536 goto out;
5537 }
5538
5539 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5540 if (!newuser) {
5541 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5542 err_code |= ERR_ALERT | ERR_ABORT;
5543 goto out;
5544 }
5545
5546 newuser->user = strdup(args[1]);
5547
5548 newuser->next = userlist->users;
5549 userlist->users = newuser;
5550
5551 cur_arg = 2;
5552
5553 while (*args[cur_arg]) {
5554 if (!strcmp(args[cur_arg], "password")) {
5555#ifndef CONFIG_HAP_CRYPT
5556 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5557 file, linenum);
5558 err_code |= ERR_ALERT;
5559#endif
5560 newuser->pass = strdup(args[cur_arg + 1]);
5561 cur_arg += 2;
5562 continue;
5563 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5564 newuser->pass = strdup(args[cur_arg + 1]);
5565 newuser->flags |= AU_O_INSECURE;
5566 cur_arg += 2;
5567 continue;
5568 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005569 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005570 cur_arg += 2;
5571 continue;
5572 } else {
5573 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5574 file, linenum, args[0]);
5575 err_code |= ERR_ALERT | ERR_FATAL;
5576 goto out;
5577 }
5578 }
5579 } else {
5580 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5581 err_code |= ERR_ALERT | ERR_FATAL;
5582 }
5583
5584out:
5585 return err_code;
5586}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587
5588/*
5589 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005590 * Returns the error code, 0 if OK, or any combination of :
5591 * - ERR_ABORT: must abort ASAP
5592 * - ERR_FATAL: we can continue parsing but not start the service
5593 * - ERR_WARN: a warning has been emitted
5594 * - ERR_ALERT: an alert has been emitted
5595 * Only the two first ones can stop processing, the two others are just
5596 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005598int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005600 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 FILE *f;
5602 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005604 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 if ((f=fopen(file,"r")) == NULL)
5607 return -1;
5608
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005609 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005610 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005611 char *end;
5612 char *args[MAX_LINE_ARGS + 1];
5613 char *line = thisline;
5614
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 linenum++;
5616
5617 end = line + strlen(line);
5618
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005619 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5620 /* Check if we reached the limit and the last char is not \n.
5621 * Watch out for the last line without the terminating '\n'!
5622 */
5623 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005624 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005625 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005626 }
5627
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005629 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005630 line++;
5631
5632 arg = 0;
5633 args[arg] = line;
5634
5635 while (*line && arg < MAX_LINE_ARGS) {
5636 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5637 * C equivalent value. Other combinations left unchanged (eg: \1).
5638 */
5639 if (*line == '\\') {
5640 int skip = 0;
5641 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5642 *line = line[1];
5643 skip = 1;
5644 }
5645 else if (line[1] == 'r') {
5646 *line = '\r';
5647 skip = 1;
5648 }
5649 else if (line[1] == 'n') {
5650 *line = '\n';
5651 skip = 1;
5652 }
5653 else if (line[1] == 't') {
5654 *line = '\t';
5655 skip = 1;
5656 }
5657 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005658 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005659 unsigned char hex1, hex2;
5660 hex1 = toupper(line[2]) - '0';
5661 hex2 = toupper(line[3]) - '0';
5662 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5663 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5664 *line = (hex1<<4) + hex2;
5665 skip = 3;
5666 }
5667 else {
5668 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005669 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 }
5671 }
5672 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005673 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 end -= skip;
5675 }
5676 line++;
5677 }
5678 else if (*line == '#' || *line == '\n' || *line == '\r') {
5679 /* end of string, end of loop */
5680 *line = 0;
5681 break;
5682 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005683 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005685 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005686 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 line++;
5688 args[++arg] = line;
5689 }
5690 else {
5691 line++;
5692 }
5693 }
5694
5695 /* empty line */
5696 if (!**args)
5697 continue;
5698
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005699 if (*line) {
5700 /* we had to stop due to too many args.
5701 * Let's terminate the string, print the offending part then cut the
5702 * last arg.
5703 */
5704 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5705 line++;
5706 *line = '\0';
5707
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005708 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005709 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005710 err_code |= ERR_ALERT | ERR_FATAL;
5711 args[arg] = line;
5712 }
5713
Willy Tarreau540abe42007-05-02 20:50:16 +02005714 /* zero out remaining args and ensure that at least one entry
5715 * is zeroed out.
5716 */
5717 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718 args[arg] = line;
5719 }
5720
Willy Tarreau3842f002009-06-14 11:39:52 +02005721 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005722 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005723 char *tmp;
5724
Willy Tarreau3842f002009-06-14 11:39:52 +02005725 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005726 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005727 for (arg=0; *args[arg+1]; arg++)
5728 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005729 *tmp = '\0'; // fix the next arg to \0
5730 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005731 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005732 else if (!strcmp(args[0], "default")) {
5733 kwm = KWM_DEF;
5734 for (arg=0; *args[arg+1]; arg++)
5735 args[arg] = args[arg+1]; // shift args after inversion
5736 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005737
William Lallemand0f99e342011-10-12 17:50:54 +02005738 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5739 strcmp(args[0], "log") != 0) {
5740 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005741 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005742 }
5743
Willy Tarreau977b8e42006-12-29 14:19:17 +01005744 if (!strcmp(args[0], "listen") ||
5745 !strcmp(args[0], "frontend") ||
5746 !strcmp(args[0], "backend") ||
5747 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005748 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005750 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005751 cursection = strdup(args[0]);
5752 }
5753 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005755 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005756 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005757 }
5758 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005759 confsect = CFG_USERLIST;
5760 free(cursection);
5761 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005762 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005763 else if (!strcmp(args[0], "peers")) {
5764 confsect = CFG_PEERS;
5765 free(cursection);
5766 cursection = strdup(args[0]);
5767 }
5768
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 /* else it's a section keyword */
5770
5771 switch (confsect) {
5772 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005773 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 break;
5775 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005776 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005778 case CFG_USERLIST:
5779 err_code |= cfg_parse_users(file, linenum, args, kwm);
5780 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005781 case CFG_PEERS:
5782 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5783 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005785 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005786 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005788
5789 if (err_code & ERR_ABORT)
5790 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005792 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005793 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005795 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005796}
5797
Willy Tarreaubb925012009-07-23 13:36:36 +02005798/*
5799 * Returns the error code, 0 if OK, or any combination of :
5800 * - ERR_ABORT: must abort ASAP
5801 * - ERR_FATAL: we can continue parsing but not start the service
5802 * - ERR_WARN: a warning has been emitted
5803 * - ERR_ALERT: an alert has been emitted
5804 * Only the two first ones can stop processing, the two others are just
5805 * indicators.
5806 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005807int check_config_validity()
5808{
5809 int cfgerr = 0;
5810 struct proxy *curproxy = NULL;
5811 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005812 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005813 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005814 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005815 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005817 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005818 /*
5819 * Now, check for the integrity of all that we have collected.
5820 */
5821
5822 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005823 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824
Willy Tarreau193b8c62012-11-22 00:17:38 +01005825 if (!global.tune.max_http_hdr)
5826 global.tune.max_http_hdr = MAX_HTTP_HDR;
5827
5828 if (!global.tune.cookie_len)
5829 global.tune.cookie_len = CAPTURE_LEN;
5830
5831 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5832
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005833 /* first, we will invert the proxy list order */
5834 curproxy = NULL;
5835 while (proxy) {
5836 struct proxy *next;
5837
5838 next = proxy->next;
5839 proxy->next = curproxy;
5840 curproxy = proxy;
5841 if (!next)
5842 break;
5843 proxy = next;
5844 }
5845
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005847 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005848 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005849 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005850 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005851 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005852 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005853 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005854
Willy Tarreau050536d2012-10-04 08:47:34 +02005855 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005856 /* proxy ID not set, use automatic numbering with first
5857 * spare entry starting with next_pxid.
5858 */
5859 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5860 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5861 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005862 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005863 next_pxid++;
5864
Willy Tarreau55ea7572007-06-17 19:56:27 +02005865
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005867 /* ensure we don't keep listeners uselessly bound */
5868 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869 curproxy = curproxy->next;
5870 continue;
5871 }
5872
Willy Tarreau16a21472012-11-19 12:39:59 +01005873 /* number of processes this proxy is bound to */
5874 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5875
Willy Tarreauff01a212009-03-15 13:46:16 +01005876 switch (curproxy->mode) {
5877 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005878 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005879 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005880 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5881 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005882 cfgerr++;
5883 }
5884
5885 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005886 Warning("config : servers will be ignored for %s '%s'.\n",
5887 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005888 break;
5889
5890 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005891 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005892 break;
5893
5894 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005895 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005896 break;
5897 }
5898
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005899 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005900 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005901 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005902 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5903 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005904 cfgerr++;
5905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005907 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005908 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5909 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005910 cfgerr++;
5911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005913 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005914 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5915 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005916 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005917 }
5918 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005919 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005920 /* If no LB algo is set in a backend, and we're not in
5921 * transparent mode, dispatch mode nor proxy mode, we
5922 * want to use balance roundrobin by default.
5923 */
5924 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5925 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 }
5927 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005928
Willy Tarreau1620ec32011-08-06 17:05:02 +02005929 if (curproxy->options & PR_O_DISPATCH)
5930 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5931 else if (curproxy->options & PR_O_HTTP_PROXY)
5932 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5933 else if (curproxy->options & PR_O_TRANSP)
5934 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005935
Willy Tarreau1620ec32011-08-06 17:05:02 +02005936 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5937 if (curproxy->options & PR_O_DISABLE404) {
5938 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5939 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5940 err_code |= ERR_WARN;
5941 curproxy->options &= ~PR_O_DISABLE404;
5942 }
5943 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5944 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5945 "send-state", proxy_type_str(curproxy), curproxy->id);
5946 err_code |= ERR_WARN;
5947 curproxy->options &= ~PR_O2_CHK_SNDST;
5948 }
Willy Tarreauef781042010-01-27 11:53:01 +01005949 }
5950
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005951 /* if a default backend was specified, let's find it */
5952 if (curproxy->defbe.name) {
5953 struct proxy *target;
5954
Alex Williams96532db2009-11-01 21:27:13 -05005955 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005956 if (!target) {
5957 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5958 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005959 cfgerr++;
5960 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005961 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5962 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005963 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005964 } else {
5965 free(curproxy->defbe.name);
5966 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005967 /* we force the backend to be present on at least all of
5968 * the frontend's processes.
5969 */
5970 target->bind_proc = curproxy->bind_proc ?
5971 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005972
5973 /* Emit a warning if this proxy also has some servers */
5974 if (curproxy->srv) {
5975 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5976 curproxy->id);
5977 err_code |= ERR_WARN;
5978 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005979 }
5980 }
5981
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005982 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005983 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5984 /* map jump target for ACT_SETBE in req_rep chain */
5985 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005986 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005987 struct proxy *target;
5988
Willy Tarreaua496b602006-12-17 23:15:24 +01005989 if (exp->action != ACT_SETBE)
5990 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005991
Alex Williams96532db2009-11-01 21:27:13 -05005992 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005993 if (!target) {
5994 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5995 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005996 cfgerr++;
5997 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005998 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5999 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006000 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006001 } else {
6002 free((void *)exp->replace);
6003 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006004 /* we force the backend to be present on at least all of
6005 * the frontend's processes.
6006 */
6007 target->bind_proc = curproxy->bind_proc ?
6008 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006009 }
6010 }
6011 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006012
6013 /* find the target proxy for 'use_backend' rules */
6014 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006015 struct proxy *target;
6016
Alex Williams96532db2009-11-01 21:27:13 -05006017 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006018
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006019 if (!target) {
6020 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6021 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006022 cfgerr++;
6023 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006024 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6025 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006026 cfgerr++;
6027 } else {
6028 free((void *)rule->be.name);
6029 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006030 /* we force the backend to be present on at least all of
6031 * the frontend's processes.
6032 */
6033 target->bind_proc = curproxy->bind_proc ?
6034 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006035 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006036 }
6037
6038 /* find the target proxy for 'use_backend' rules */
6039 list_for_each_entry(srule, &curproxy->server_rules, list) {
6040 struct server *target = findserver(curproxy, srule->srv.name);
6041
6042 if (!target) {
6043 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6044 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6045 cfgerr++;
6046 continue;
6047 }
6048 free((void *)srule->srv.name);
6049 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006050 }
6051
Emeric Brunb982a3d2010-01-04 15:45:53 +01006052 /* find the target table for 'stick' rules */
6053 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6054 struct proxy *target;
6055
Emeric Brun1d33b292010-01-04 15:47:17 +01006056 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6057 if (mrule->flags & STK_IS_STORE)
6058 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6059
Emeric Brunb982a3d2010-01-04 15:45:53 +01006060 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006061 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006062 else
6063 target = curproxy;
6064
6065 if (!target) {
6066 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6067 curproxy->id, mrule->table.name);
6068 cfgerr++;
6069 }
6070 else if (target->table.size == 0) {
6071 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6072 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6073 cfgerr++;
6074 }
Willy Tarreau12785782012-04-27 21:37:17 +02006075 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6076 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006077 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6078 cfgerr++;
6079 }
6080 else {
6081 free((void *)mrule->table.name);
6082 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006083 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006084 }
6085 }
6086
6087 /* find the target table for 'store response' rules */
6088 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6089 struct proxy *target;
6090
Emeric Brun1d33b292010-01-04 15:47:17 +01006091 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6092
Emeric Brunb982a3d2010-01-04 15:45:53 +01006093 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006094 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006095 else
6096 target = curproxy;
6097
6098 if (!target) {
6099 Alert("Proxy '%s': unable to find store table '%s'.\n",
6100 curproxy->id, mrule->table.name);
6101 cfgerr++;
6102 }
6103 else if (target->table.size == 0) {
6104 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6105 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6106 cfgerr++;
6107 }
Willy Tarreau12785782012-04-27 21:37:17 +02006108 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6109 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006110 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6111 cfgerr++;
6112 }
6113 else {
6114 free((void *)mrule->table.name);
6115 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006116 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006117 }
6118 }
6119
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006120 /* find the target table for 'tcp-request' layer 4 rules */
6121 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6122 struct proxy *target;
6123
Willy Tarreau56123282010-08-06 19:06:56 +02006124 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006125 continue;
6126
6127 if (trule->act_prm.trk_ctr.table.n)
6128 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6129 else
6130 target = curproxy;
6131
6132 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006133 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6134 curproxy->id, trule->act_prm.trk_ctr.table.n,
6135 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006136 cfgerr++;
6137 }
6138 else if (target->table.size == 0) {
6139 Alert("Proxy '%s': table '%s' used but not configured.\n",
6140 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6141 cfgerr++;
6142 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006143 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6144 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6145 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6146 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6147 cfgerr++;
6148 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006149 else {
6150 free(trule->act_prm.trk_ctr.table.n);
6151 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006152 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006153 * to pass a list of counters to track and allocate them right here using
6154 * stktable_alloc_data_type().
6155 */
6156 }
6157 }
6158
Willy Tarreaud1f96522010-08-03 19:34:32 +02006159 /* find the target table for 'tcp-request' layer 6 rules */
6160 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6161 struct proxy *target;
6162
Willy Tarreau56123282010-08-06 19:06:56 +02006163 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006164 continue;
6165
6166 if (trule->act_prm.trk_ctr.table.n)
6167 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6168 else
6169 target = curproxy;
6170
6171 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006172 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6173 curproxy->id, trule->act_prm.trk_ctr.table.n,
6174 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006175 cfgerr++;
6176 }
6177 else if (target->table.size == 0) {
6178 Alert("Proxy '%s': table '%s' used but not configured.\n",
6179 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6180 cfgerr++;
6181 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006182 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6183 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6184 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6185 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6186 cfgerr++;
6187 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006188 else {
6189 free(trule->act_prm.trk_ctr.table.n);
6190 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006191 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006192 * to pass a list of counters to track and allocate them right here using
6193 * stktable_alloc_data_type().
6194 */
6195 }
6196 }
6197
Emeric Brun32da3c42010-09-23 18:39:19 +02006198 if (curproxy->table.peers.name) {
6199 struct peers *curpeers = peers;
6200
6201 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6202 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6203 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006204 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006205 break;
6206 }
6207 }
6208
6209 if (!curpeers) {
6210 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6211 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006212 free((void *)curproxy->table.peers.name);
6213 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006214 cfgerr++;
6215 }
6216 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006217 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6218 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006219 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006220 cfgerr++;
6221 }
6222 }
6223
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006224 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006225 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006226 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6227 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6228 "proxy", curproxy->id);
6229 cfgerr++;
6230 goto out_uri_auth_compat;
6231 }
6232
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006233 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006234 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006235 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006236 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006237
Willy Tarreau95fa4692010-02-01 13:05:50 +01006238 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6239 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006240
6241 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006242 uri_auth_compat_req[i++] = "realm";
6243 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6244 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006245
Willy Tarreau95fa4692010-02-01 13:05:50 +01006246 uri_auth_compat_req[i++] = "unless";
6247 uri_auth_compat_req[i++] = "{";
6248 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6249 uri_auth_compat_req[i++] = "}";
6250 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006251
Willy Tarreauff011f22011-01-06 17:51:27 +01006252 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6253 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006254 cfgerr++;
6255 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006256 }
6257
Willy Tarreauff011f22011-01-06 17:51:27 +01006258 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006259
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006260 if (curproxy->uri_auth->auth_realm) {
6261 free(curproxy->uri_auth->auth_realm);
6262 curproxy->uri_auth->auth_realm = NULL;
6263 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006264
6265 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006266 }
6267out_uri_auth_compat:
6268
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006269 cfgerr += acl_find_targets(curproxy);
6270
Willy Tarreau2738a142006-07-08 17:28:09 +02006271 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006272 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006273 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006274 (!curproxy->timeout.connect ||
6275 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006276 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006277 " | While not properly invalid, you will certainly encounter various problems\n"
6278 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006279 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006280 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006281 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006282 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006283
Willy Tarreau1fa31262007-12-03 00:36:16 +01006284 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6285 * We must still support older configurations, so let's find out whether those
6286 * parameters have been set or must be copied from contimeouts.
6287 */
6288 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006289 if (!curproxy->timeout.tarpit ||
6290 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006291 /* tarpit timeout not set. We search in the following order:
6292 * default.tarpit, curr.connect, default.connect.
6293 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006294 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006295 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006296 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006297 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006298 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006299 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006300 }
6301 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006302 (!curproxy->timeout.queue ||
6303 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006304 /* queue timeout not set. We search in the following order:
6305 * default.queue, curr.connect, default.connect.
6306 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006307 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006308 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006309 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006310 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006311 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006312 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006313 }
6314 }
6315
Willy Tarreau1620ec32011-08-06 17:05:02 +02006316 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006317 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6318 curproxy->check_req = (char *)malloc(curproxy->check_len);
6319 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006320 }
6321
Willy Tarreau193b8c62012-11-22 00:17:38 +01006322 /* ensure that cookie capture length is not too large */
6323 if (curproxy->capture_len >= global.tune.cookie_len) {
6324 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6325 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6326 err_code |= ERR_WARN;
6327 curproxy->capture_len = global.tune.cookie_len - 1;
6328 }
6329
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006330 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006331 if (curproxy->nb_req_cap) {
6332 if (curproxy->mode == PR_MODE_HTTP) {
6333 curproxy->req_cap_pool = create_pool("ptrcap",
6334 curproxy->nb_req_cap * sizeof(char *),
6335 MEM_F_SHARED);
6336 } else {
6337 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6338 proxy_type_str(curproxy), curproxy->id);
6339 err_code |= ERR_WARN;
6340 curproxy->to_log &= ~LW_REQHDR;
6341 curproxy->nb_req_cap = 0;
6342 }
6343 }
6344
6345 if (curproxy->nb_rsp_cap) {
6346 if (curproxy->mode == PR_MODE_HTTP) {
6347 curproxy->rsp_cap_pool = create_pool("ptrcap",
6348 curproxy->nb_rsp_cap * sizeof(char *),
6349 MEM_F_SHARED);
6350 } else {
6351 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6352 proxy_type_str(curproxy), curproxy->id);
6353 err_code |= ERR_WARN;
6354 curproxy->to_log &= ~LW_REQHDR;
6355 curproxy->nb_rsp_cap = 0;
6356 }
6357 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006358
Willy Tarreau196729e2012-05-31 19:30:26 +02006359 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006360 if (!(curproxy->cap & PR_CAP_FE)) {
6361 if (curproxy->logformat_string != default_http_log_format &&
6362 curproxy->logformat_string != default_tcp_log_format &&
6363 curproxy->logformat_string != clf_http_log_format)
6364 free(curproxy->logformat_string);
6365 curproxy->logformat_string = NULL;
6366 }
6367
Willy Tarreau196729e2012-05-31 19:30:26 +02006368 if (curproxy->logformat_string)
6369 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6370
6371 if (curproxy->uniqueid_format_string)
6372 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6373
Willy Tarreaubaaee002006-06-26 02:48:02 +02006374 /* first, we will invert the servers list order */
6375 newsrv = NULL;
6376 while (curproxy->srv) {
6377 struct server *next;
6378
6379 next = curproxy->srv->next;
6380 curproxy->srv->next = newsrv;
6381 newsrv = curproxy->srv;
6382 if (!next)
6383 break;
6384 curproxy->srv = next;
6385 }
6386
Willy Tarreaudd701652010-05-25 23:03:02 +02006387 /* assign automatic UIDs to servers which don't have one yet */
6388 next_id = 1;
6389 newsrv = curproxy->srv;
6390 while (newsrv != NULL) {
6391 if (!newsrv->puid) {
6392 /* server ID not set, use automatic numbering with first
6393 * spare entry starting with next_svid.
6394 */
6395 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6396 newsrv->conf.id.key = newsrv->puid = next_id;
6397 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6398 }
6399 next_id++;
6400 newsrv = newsrv->next;
6401 }
6402
Willy Tarreau20697042007-11-15 23:26:18 +01006403 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006404 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006405
Willy Tarreau62c3be22012-01-20 13:12:32 +01006406 /*
6407 * If this server supports a maxconn parameter, it needs a dedicated
6408 * tasks to fill the emptied slots when a connection leaves.
6409 * Also, resolve deferred tracking dependency if needed.
6410 */
6411 newsrv = curproxy->srv;
6412 while (newsrv != NULL) {
6413 if (newsrv->minconn > newsrv->maxconn) {
6414 /* Only 'minconn' was specified, or it was higher than or equal
6415 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6416 * this will avoid further useless expensive computations.
6417 */
6418 newsrv->maxconn = newsrv->minconn;
6419 } else if (newsrv->maxconn && !newsrv->minconn) {
6420 /* minconn was not specified, so we set it to maxconn */
6421 newsrv->minconn = newsrv->maxconn;
6422 }
6423
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006424#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006425 if (newsrv->use_ssl || newsrv->check.use_ssl)
6426 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006427#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006428
Willy Tarreau62c3be22012-01-20 13:12:32 +01006429 if (newsrv->trackit) {
6430 struct proxy *px;
6431 struct server *srv;
6432 char *pname, *sname;
6433
6434 pname = newsrv->trackit;
6435 sname = strrchr(pname, '/');
6436
6437 if (sname)
6438 *sname++ = '\0';
6439 else {
6440 sname = pname;
6441 pname = NULL;
6442 }
6443
6444 if (pname) {
6445 px = findproxy(pname, PR_CAP_BE);
6446 if (!px) {
6447 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6448 proxy_type_str(curproxy), curproxy->id,
6449 newsrv->id, pname);
6450 cfgerr++;
6451 goto next_srv;
6452 }
6453 } else
6454 px = curproxy;
6455
6456 srv = findserver(px, sname);
6457 if (!srv) {
6458 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6459 proxy_type_str(curproxy), curproxy->id,
6460 newsrv->id, sname);
6461 cfgerr++;
6462 goto next_srv;
6463 }
6464
6465 if (!(srv->state & SRV_CHECKED)) {
6466 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6467 "tracking as it does not have checks enabled.\n",
6468 proxy_type_str(curproxy), curproxy->id,
6469 newsrv->id, px->id, srv->id);
6470 cfgerr++;
6471 goto next_srv;
6472 }
6473
6474 if (curproxy != px &&
6475 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6476 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6477 "tracking: disable-on-404 option inconsistency.\n",
6478 proxy_type_str(curproxy), curproxy->id,
6479 newsrv->id, px->id, srv->id);
6480 cfgerr++;
6481 goto next_srv;
6482 }
6483
6484 /* if the other server is forced disabled, we have to do the same here */
6485 if (srv->state & SRV_MAINTAIN) {
6486 newsrv->state |= SRV_MAINTAIN;
6487 newsrv->state &= ~SRV_RUNNING;
6488 newsrv->health = 0;
6489 }
6490
6491 newsrv->track = srv;
6492 newsrv->tracknext = srv->tracknext;
6493 srv->tracknext = newsrv;
6494
6495 free(newsrv->trackit);
6496 newsrv->trackit = NULL;
6497 }
6498 next_srv:
6499 newsrv = newsrv->next;
6500 }
6501
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006502 /* We have to initialize the server lookup mechanism depending
6503 * on what LB algorithm was choosen.
6504 */
6505
6506 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6507 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6508 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006509 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6510 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6511 init_server_map(curproxy);
6512 } else {
6513 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6514 fwrr_init_server_groups(curproxy);
6515 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006516 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006517
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006518 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006519 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6520 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6521 fwlc_init_server_tree(curproxy);
6522 } else {
6523 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6524 fas_init_server_tree(curproxy);
6525 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006526 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006527
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006528 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006529 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6530 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6531 chash_init_server_tree(curproxy);
6532 } else {
6533 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6534 init_server_map(curproxy);
6535 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006536 break;
6537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538
6539 if (curproxy->options & PR_O_LOGASAP)
6540 curproxy->to_log &= ~LW_BYTES;
6541
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006542 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006543 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006544 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6545 proxy_type_str(curproxy), curproxy->id);
6546 err_code |= ERR_WARN;
6547 }
6548
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006549 if (curproxy->mode != PR_MODE_HTTP) {
6550 int optnum;
6551
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006552 if (curproxy->uri_auth) {
6553 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6554 proxy_type_str(curproxy), curproxy->id);
6555 err_code |= ERR_WARN;
6556 curproxy->uri_auth = NULL;
6557 }
6558
Willy Tarreau87cf5142011-08-19 22:57:24 +02006559 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006560 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6561 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6562 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006563 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006564 }
6565
6566 if (curproxy->options & PR_O_ORGTO) {
6567 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6568 "originalto", proxy_type_str(curproxy), curproxy->id);
6569 err_code |= ERR_WARN;
6570 curproxy->options &= ~PR_O_ORGTO;
6571 }
6572
6573 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6574 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6575 (curproxy->cap & cfg_opts[optnum].cap) &&
6576 (curproxy->options & cfg_opts[optnum].val)) {
6577 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6578 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6579 err_code |= ERR_WARN;
6580 curproxy->options &= ~cfg_opts[optnum].val;
6581 }
6582 }
6583
6584 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6585 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6586 (curproxy->cap & cfg_opts2[optnum].cap) &&
6587 (curproxy->options2 & cfg_opts2[optnum].val)) {
6588 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6589 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6590 err_code |= ERR_WARN;
6591 curproxy->options2 &= ~cfg_opts2[optnum].val;
6592 }
6593 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006594
Willy Tarreauefa5f512010-03-30 20:13:29 +02006595#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006596 if (curproxy->conn_src.bind_hdr_occ) {
6597 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006598 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006599 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006600 err_code |= ERR_WARN;
6601 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006602#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006603 }
6604
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006606 * ensure that we're not cross-dressing a TCP server into HTTP.
6607 */
6608 newsrv = curproxy->srv;
6609 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006610 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006611 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6612 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006613 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006614 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006615
Willy Tarreau0cec3312011-10-31 13:49:26 +01006616 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6617 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6618 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6619 err_code |= ERR_WARN;
6620 }
6621
Willy Tarreauefa5f512010-03-30 20:13:29 +02006622#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006623 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6624 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006625 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 +01006626 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006627 err_code |= ERR_WARN;
6628 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006629#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006630 newsrv = newsrv->next;
6631 }
6632
Willy Tarreauc1a21672009-08-16 22:37:44 +02006633 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006634 if (!curproxy->accept)
6635 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006636
Willy Tarreauc1a21672009-08-16 22:37:44 +02006637 if (curproxy->tcp_req.inspect_delay ||
6638 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006639 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006640
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006641 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006642 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006643 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006644 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006645
6646 /* both TCP and HTTP must check switching rules */
6647 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6648 }
6649
6650 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006651 if (curproxy->tcp_req.inspect_delay ||
6652 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6653 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6654
Emeric Brun97679e72010-09-23 17:56:44 +02006655 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6656 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6657
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006658 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006659 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006660 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006661 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006662
6663 /* If the backend does requires RDP cookie persistence, we have to
6664 * enable the corresponding analyser.
6665 */
6666 if (curproxy->options2 & PR_O2_RDPC_PRST)
6667 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6668 }
6669
Emeric Brunc52962f2012-11-15 18:28:02 +01006670#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006671 /* Configure SSL for each bind line.
6672 * Note: if configuration fails at some point, the ->ctx member
6673 * remains NULL so that listeners can later detach.
6674 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006675 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006676 if (!bind_conf->is_ssl) {
6677 if (bind_conf->default_ctx) {
6678 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6679 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6680 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006681 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006682 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006683 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006684 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006685 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006686 cfgerr++;
6687 continue;
6688 }
6689
Emeric Brun4b3091e2012-09-24 15:48:52 +02006690 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006691 Alert("Unable to allocate SSL session cache.\n");
6692 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006693 continue;
6694 }
6695
Emeric Brunfc0421f2012-09-07 17:30:07 +02006696 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006697 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006698 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006699#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006700
Willy Tarreaue6b98942007-10-29 01:09:36 +01006701 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006702 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006703 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006704 if (!listener->luid) {
6705 /* listener ID not set, use automatic numbering with first
6706 * spare entry starting with next_luid.
6707 */
6708 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6709 listener->conf.id.key = listener->luid = next_id;
6710 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006711 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006712 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006713
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006714 /* enable separate counters */
6715 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6716 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006717 if (!listener->name)
6718 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006719 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006720
Willy Tarreaue6b98942007-10-29 01:09:36 +01006721 if (curproxy->options & PR_O_TCP_NOLING)
6722 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006723 if (!listener->maxconn)
6724 listener->maxconn = curproxy->maxconn;
6725 if (!listener->backlog)
6726 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006727 if (!listener->maxaccept)
6728 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6729
6730 /* we want to have an optimal behaviour on single process mode to
6731 * maximize the work at once, but in multi-process we want to keep
6732 * some fairness between processes, so we target half of the max
6733 * number of events to be balanced over all the processes the proxy
6734 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6735 * used to disable the limit.
6736 */
6737 if (listener->maxaccept > 0) {
6738 if (nbproc > 1)
6739 listener->maxaccept = (listener->maxaccept + 1) / 2;
6740 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6741 }
6742
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006743 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006744 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006745 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006746 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006747
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006748 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6749 listener->options |= LI_O_TCP_RULES;
6750
Willy Tarreaude3041d2010-05-31 10:56:17 +02006751 if (curproxy->mon_mask.s_addr)
6752 listener->options |= LI_O_CHK_MONNET;
6753
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006754 /* smart accept mode is automatic in HTTP mode */
6755 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006756 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006757 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6758 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006759 }
6760
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006761 /* Release unused SSL configs */
6762 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6763 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006764 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006765#ifdef USE_OPENSSL
6766 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006767 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006768 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006769 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006770 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006771#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006772 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006773
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006774 /* Check multi-process mode compatibility for the current proxy */
6775 if (global.nbproc > 1) {
6776 int nbproc = 0;
6777 if (curproxy->bind_proc) {
6778 int proc;
6779 for (proc = 0; proc < global.nbproc; proc++) {
6780 if (curproxy->bind_proc & (1 << proc)) {
6781 nbproc++;
6782 }
6783 }
6784 } else {
6785 nbproc = global.nbproc;
6786 }
6787 if (curproxy->table.peers.name) {
6788 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6789 curproxy->id);
6790 cfgerr++;
6791 }
6792 if (nbproc > 1) {
6793 if (curproxy->uri_auth) {
6794 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6795 curproxy->id);
6796 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6797 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6798 curproxy->id);
6799 }
6800 }
6801 if (curproxy->appsession_name) {
6802 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6803 curproxy->id);
6804 }
6805 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6806 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6807 curproxy->id);
6808 }
6809 }
6810 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006811
6812 /* create the task associated with the proxy */
6813 curproxy->task = task_new();
6814 if (curproxy->task) {
6815 curproxy->task->context = curproxy;
6816 curproxy->task->process = manage_proxy;
6817 /* no need to queue, it will be done automatically if some
6818 * listener gets limited.
6819 */
6820 curproxy->task->expire = TICK_ETERNITY;
6821 } else {
6822 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6823 curproxy->id);
6824 cfgerr++;
6825 }
6826
Willy Tarreaubaaee002006-06-26 02:48:02 +02006827 curproxy = curproxy->next;
6828 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006829
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006830 /* Check multi-process mode compatibility */
6831 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006832 if (global.stats_fe && !global.stats_fe->bind_proc) {
6833 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 +01006834 }
6835 }
6836
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006837 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6838 struct auth_users *curuser;
6839 int g;
6840
6841 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6842 unsigned int group_mask = 0;
6843 char *group = NULL;
6844
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006845 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006846 continue;
6847
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006848 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006849
6850 for (g = 0; g < curuserlist->grpcnt; g++)
6851 if (!strcmp(curuserlist->groups[g], group))
6852 break;
6853
6854 if (g == curuserlist->grpcnt) {
6855 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6856 curuserlist->name, group, curuser->user);
6857 err_code |= ERR_ALERT | ERR_FATAL;
6858 goto out;
6859 }
6860
6861 group_mask |= (1 << g);
6862 }
6863
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006864 free(curuser->u.groups);
6865 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006866 }
6867
6868 for (g = 0; g < curuserlist->grpcnt; g++) {
6869 char *user = NULL;
6870
6871 if (!curuserlist->groupusers[g])
6872 continue;
6873
6874 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6875 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6876 if (!strcmp(curuser->user, user))
6877 break;
6878
6879 if (!curuser) {
6880 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6881 curuserlist->name, user, curuserlist->groups[g]);
6882 err_code |= ERR_ALERT | ERR_FATAL;
6883 goto out;
6884 }
6885
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006886 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006887 }
6888
6889 free(curuserlist->groupusers[g]);
6890 }
6891
6892 free(curuserlist->groupusers);
6893
6894#ifdef DEBUG_AUTH
6895 for (g = 0; g < curuserlist->grpcnt; g++) {
6896 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6897
6898 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006899 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006900 fprintf(stderr, " %s", curuser->user);
6901 }
6902
6903 fprintf(stderr, "\n");
6904 }
6905#endif
6906
Willy Tarreaufbb78422011-06-05 15:38:35 +02006907 }
6908
6909 /* automatically compute fullconn if not set. We must not do it in the
6910 * loop above because cross-references are not yet fully resolved.
6911 */
6912 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6913 /* If <fullconn> is not set, let's set it to 10% of the sum of
6914 * the possible incoming frontend's maxconns.
6915 */
6916 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6917 struct proxy *fe;
6918 int total = 0;
6919
6920 /* sum up the number of maxconns of frontends which
6921 * reference this backend at least once or which are
6922 * the same one ('listen').
6923 */
6924 for (fe = proxy; fe; fe = fe->next) {
6925 struct switching_rule *rule;
6926 struct hdr_exp *exp;
6927 int found = 0;
6928
6929 if (!(fe->cap & PR_CAP_FE))
6930 continue;
6931
6932 if (fe == curproxy) /* we're on a "listen" instance */
6933 found = 1;
6934
6935 if (fe->defbe.be == curproxy) /* "default_backend" */
6936 found = 1;
6937
6938 /* check if a "use_backend" rule matches */
6939 if (!found) {
6940 list_for_each_entry(rule, &fe->switching_rules, list) {
6941 if (rule->be.backend == curproxy) {
6942 found = 1;
6943 break;
6944 }
6945 }
6946 }
6947
6948 /* check if a "reqsetbe" rule matches */
6949 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6950 if (exp->action == ACT_SETBE &&
6951 (struct proxy *)exp->replace == curproxy) {
6952 found = 1;
6953 break;
6954 }
6955 }
6956
6957 /* now we've checked all possible ways to reference a backend
6958 * from a frontend.
6959 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006960 if (!found)
6961 continue;
6962 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006963 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006964 /* we have the sum of the maxconns in <total>. We only
6965 * keep 10% of that sum to set the default fullconn, with
6966 * a hard minimum of 1 (to avoid a divide by zero).
6967 */
6968 curproxy->fullconn = (total + 9) / 10;
6969 if (!curproxy->fullconn)
6970 curproxy->fullconn = 1;
6971 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006972 }
6973
Willy Tarreau056f5682010-06-06 15:51:11 +02006974 /* initialize stick-tables on backend capable proxies. This must not
6975 * be done earlier because the data size may be discovered while parsing
6976 * other proxies.
6977 */
6978 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006979 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006980
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006981 /*
6982 * Recount currently required checks.
6983 */
6984
6985 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6986 int optnum;
6987
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006988 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6989 if (curproxy->options & cfg_opts[optnum].val)
6990 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006991
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006992 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6993 if (curproxy->options2 & cfg_opts2[optnum].val)
6994 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006995 }
6996
Willy Tarreau122541c2011-09-07 21:24:49 +02006997 if (peers) {
6998 struct peers *curpeers = peers, **last;
6999 struct peer *p, *pb;
7000
7001 /* Remove all peers sections which don't have a valid listener.
7002 * This can happen when a peers section is never referenced and
7003 * does not contain a local peer.
7004 */
7005 last = &peers;
7006 while (*last) {
7007 curpeers = *last;
7008 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007009 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007010 last = &curpeers->next;
7011 continue;
7012 }
7013
7014 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7015 curpeers->id, localpeer);
7016
7017 p = curpeers->remote;
7018 while (p) {
7019 pb = p->next;
7020 free(p->id);
7021 free(p);
7022 p = pb;
7023 }
7024
7025 /* Destroy and unlink this curpeers section.
7026 * Note: curpeers is backed up into *last.
7027 */
7028 free(curpeers->id);
7029 curpeers = curpeers->next;
7030 free(*last);
7031 *last = curpeers;
7032 }
7033 }
7034
Willy Tarreau34eb6712011-10-24 18:15:04 +02007035 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007036 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007037 MEM_F_SHARED);
7038
Willy Tarreaubb925012009-07-23 13:36:36 +02007039 if (cfgerr > 0)
7040 err_code |= ERR_ALERT | ERR_FATAL;
7041 out:
7042 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007043}
7044
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007045/*
7046 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7047 * parsing sessions.
7048 */
7049void cfg_register_keywords(struct cfg_kw_list *kwl)
7050{
7051 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7052}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007053
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007054/*
7055 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7056 */
7057void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7058{
7059 LIST_DEL(&kwl->list);
7060 LIST_INIT(&kwl->list);
7061}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007062
7063/*
7064 * Local variables:
7065 * c-indent-level: 8
7066 * c-basic-offset: 8
7067 * End:
7068 */