blob: 4954e7ace801e53a7939f1281280397412f99574 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
209 struct sockaddr_storage ss;
210
211 str = next;
212 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100213 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 *next++ = 0;
215 }
216
Emeric Bruned760922010-10-22 17:59:25 +0200217 if (*str == '/') {
218 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
219 /* so compute max path */
220 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
221 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Emeric Bruned760922010-10-22 17:59:25 +0200223 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200225 goto fail;
226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200229 ss.ss_family = AF_UNIX;
230 if (global.unix_bind.prefix) {
231 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
232 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 }
Emeric Bruned760922010-10-22 17:59:25 +0200234 else {
235 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
236 }
237 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 }
239 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100240 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 ss2 = str2sa_range(str, &port, &end);
243 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 if (!port) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100253 /* OK the address looks correct */
254 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
Emeric Bruned760922010-10-22 17:59:25 +0200256 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200257 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
260
261 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
266
267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100269 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200270 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
271 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
272 l->frontend = curproxy;
273 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
275 l->fd = -1;
276 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200277 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 l->state = LI_INIT;
279
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100280 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 tcpv4_add_listener(l);
283 }
Emeric Bruned760922010-10-22 17:59:25 +0200284 else if (ss.ss_family == AF_INET6) {
285 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
286 tcpv6_add_listener(l);
287 }
288 else {
Emeric Bruned760922010-10-22 17:59:25 +0200289 uxst_add_listener(l);
290 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200292 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 } /* end for(port) */
295 } /* end while(next) */
296 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200297 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 fail:
299 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200300 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301}
302
Willy Tarreau977b8e42006-12-29 14:19:17 +0100303/*
304 * Sends a warning if proxy <proxy> does not have at least one of the
305 * capabilities in <cap>. An optionnal <hint> may be added at the end
306 * of the warning to help the user. Returns 1 if a warning was emitted
307 * or 0 if the condition is valid.
308 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100309int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100310{
311 char *msg;
312
313 switch (cap) {
314 case PR_CAP_BE: msg = "no backend"; break;
315 case PR_CAP_FE: msg = "no frontend"; break;
316 case PR_CAP_RS: msg = "no ruleset"; break;
317 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
318 default: msg = "not enough"; break;
319 }
320
321 if (!(proxy->cap & cap)) {
322 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100323 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100324 return 1;
325 }
326 return 0;
327}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328
Willy Tarreau61d18892009-03-31 10:49:21 +0200329/* Report a warning if a rule is placed after a 'block' rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
334 if (!LIST_ISEMPTY(&proxy->block_cond)) {
335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a reqrewrite rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (proxy->req_exp) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a reqadd rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100360 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* Report a warning if a rule is placed after a redirect rule.
369 * Return 1 if the warning has been emitted, otherwise 0.
370 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100371int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200372{
373 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
374 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
375 file, line, arg);
376 return 1;
377 }
378 return 0;
379}
380
381/* Report a warning if a rule is placed after a 'use_backend' rule.
382 * Return 1 if the warning has been emitted, otherwise 0.
383 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
387 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
388 file, line, arg);
389 return 1;
390 }
391 return 0;
392}
393
394/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
398 warnif_rule_after_reqadd(proxy, file, line, arg) ||
399 warnif_rule_after_redirect(proxy, file, line, arg) ||
400 warnif_rule_after_use_backend(proxy, file, line, arg);
401}
402
403/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100404int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200405{
406 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
408 warnif_rule_after_use_backend(proxy, file, line, arg);
409}
410
411/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_redirect(proxy, file, line, arg) ||
415 warnif_rule_after_use_backend(proxy, file, line, arg);
416}
417
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418/* Report it if a request ACL condition uses some response-only parameters. It
419 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
420 * Note that <cond> may be NULL and then will be ignored.
421 */
422static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
423{
424 struct acl *acl;
425
426 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
427 return 0;
428
429 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
430 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
431 file, line, acl ? acl->name : "(unknown)");
432 return ERR_WARN;
433}
434
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100435/* Report it if a request ACL condition uses some request-only volatile parameters.
436 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
447 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 * parse a line in a <global> section. Returns the error code, 0 if OK, or
455 * any combination of :
456 * - ERR_ABORT: must abort ASAP
457 * - ERR_FATAL: we can continue parsing but not start the service
458 * - ERR_WARN: a warning has been emitted
459 * - ERR_ALERT: an alert has been emitted
460 * Only the two first ones can stop processing, the two others are just
461 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200463int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464{
Willy Tarreau058e9072009-07-20 09:30:05 +0200465 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200466 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467
468 if (!strcmp(args[0], "global")) { /* new section */
469 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200472 else if (!strcmp(args[0], "ca-base")) {
473#ifdef USE_OPENSSL
474 if (global.ca_base != NULL) {
475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
476 err_code |= ERR_ALERT;
477 goto out;
478 }
479 if (*(args[1]) == 0) {
480 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT | ERR_FATAL;
482 goto out;
483 }
484 global.ca_base = strdup(args[1]);
485#else
486 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
487 err_code |= ERR_ALERT | ERR_FATAL;
488 goto out;
489#endif
490 }
491 else if (!strcmp(args[0], "crt-base")) {
492#ifdef USE_OPENSSL
493 if (global.crt_base != NULL) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
495 err_code |= ERR_ALERT;
496 goto out;
497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
502 }
503 global.crt_base = strdup(args[1]);
504#else
505 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
506 err_code |= ERR_ALERT | ERR_FATAL;
507 goto out;
508#endif
509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510 else if (!strcmp(args[0], "daemon")) {
511 global.mode |= MODE_DAEMON;
512 }
513 else if (!strcmp(args[0], "debug")) {
514 global.mode |= MODE_DEBUG;
515 }
516 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100517 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200519 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100520 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200522 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100523 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100525 else if (!strcmp(args[0], "nosplice")) {
526 global.tune.options &= ~GTUNE_USE_SPLICE;
527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 else if (!strcmp(args[0], "quiet")) {
529 global.mode |= MODE_QUIET;
530 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200531 else if (!strcmp(args[0], "tune.maxpollevents")) {
532 if (global.tune.maxpollevents != 0) {
533 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 err_code |= ERR_ALERT;
535 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200541 }
542 global.tune.maxpollevents = atol(args[1]);
543 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100544 else if (!strcmp(args[0], "tune.maxaccept")) {
545 if (global.tune.maxaccept != 0) {
546 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 err_code |= ERR_ALERT;
548 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100554 }
555 global.tune.maxaccept = atol(args[1]);
556 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200557 else if (!strcmp(args[0], "tune.chksize")) {
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563 global.tune.chksize = atol(args[1]);
564 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200565#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100566 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.sslcachesize = atol(args[1]);
573 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100574 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
575 unsigned int ssllifetime;
576 const char *res;
577
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
582 }
583
584 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
585 if (res) {
586 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
587 file, linenum, *res, args[0]);
588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
590 }
591
592 global.tune.ssllifetime = ssllifetime;
593 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200594#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200595 else if (!strcmp(args[0], "tune.bufsize")) {
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
600 }
601 global.tune.bufsize = atol(args[1]);
602 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
603 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100604 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200605 }
606 else if (!strcmp(args[0], "tune.maxrewrite")) {
607 if (*(args[1]) == 0) {
608 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612 global.tune.maxrewrite = atol(args[1]);
613 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
614 global.tune.maxrewrite = global.tune.bufsize / 2;
615 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100616 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
617 if (global.tune.client_rcvbuf != 0) {
618 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
619 err_code |= ERR_ALERT;
620 goto out;
621 }
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.tune.client_rcvbuf = atol(args[1]);
628 }
629 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
630 if (global.tune.server_rcvbuf != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
632 err_code |= ERR_ALERT;
633 goto out;
634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
639 }
640 global.tune.server_rcvbuf = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "tune.sndbuf.client")) {
643 if (global.tune.client_sndbuf != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT;
646 goto out;
647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
652 }
653 global.tune.client_sndbuf = atol(args[1]);
654 }
655 else if (!strcmp(args[0], "tune.sndbuf.server")) {
656 if (global.tune.server_sndbuf != 0) {
657 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
658 err_code |= ERR_ALERT;
659 goto out;
660 }
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666 global.tune.server_sndbuf = atol(args[1]);
667 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200668 else if (!strcmp(args[0], "tune.pipesize")) {
669 if (*(args[1]) == 0) {
670 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674 global.tune.pipesize = atol(args[1]);
675 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100676 else if (!strcmp(args[0], "tune.http.cookielen")) {
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.cookie_len = atol(args[1]) + 1;
683 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200684 else if (!strcmp(args[0], "tune.http.maxhdr")) {
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 global.tune.max_http_hdr = atol(args[1]);
691 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100692 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
693#ifdef USE_ZLIB
694 if (*args[1]) {
695 global.tune.zlibmemlevel = atoi(args[1]);
696 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
697 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
698 file, linenum, args[0]);
699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
701 }
702 } else {
703 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
704 file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708#else
709 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712#endif
713 }
714 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
715#ifdef USE_ZLIB
716 if (*args[1]) {
717 global.tune.zlibwindowsize = atoi(args[1]);
718 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
719 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
720 file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 } else {
725 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
726 file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730#else
731 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734#endif
735 }
William Lallemandf3747832012-11-09 12:33:10 +0100736 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
737 if (*args[1]) {
738 global.tune.comp_maxlevel = atoi(args[1]);
739 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
740 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
741 file, linenum, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745 } else {
746 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
747 file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 else if (!strcmp(args[0], "uid")) {
753 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200754 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 global.uid = atol(args[1]);
764 }
765 else if (!strcmp(args[0], "gid")) {
766 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200767 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_ALERT;
769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 }
771 if (*(args[1]) == 0) {
772 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 global.gid = atol(args[1]);
777 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200778 /* user/group name handling */
779 else if (!strcmp(args[0], "user")) {
780 struct passwd *ha_user;
781 if (global.uid != 0) {
782 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200783 err_code |= ERR_ALERT;
784 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 }
786 errno = 0;
787 ha_user = getpwnam(args[1]);
788 if (ha_user != NULL) {
789 global.uid = (int)ha_user->pw_uid;
790 }
791 else {
792 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200793 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200794 }
795 }
796 else if (!strcmp(args[0], "group")) {
797 struct group *ha_group;
798 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200799 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT;
801 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200802 }
803 errno = 0;
804 ha_group = getgrnam(args[1]);
805 if (ha_group != NULL) {
806 global.gid = (int)ha_group->gr_gid;
807 }
808 else {
809 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200810 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200811 }
812 }
813 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 }
820 global.nbproc = atol(args[1]);
821 }
822 else if (!strcmp(args[0], "maxconn")) {
823 if (global.maxconn != 0) {
824 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_ALERT;
826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 global.maxconn = atol(args[1]);
834#ifdef SYSTEM_MAXCONN
835 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
836 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
837 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840#endif /* SYSTEM_MAXCONN */
841 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200842 else if (!strcmp(args[0], "maxsslconn")) {
843#ifdef USE_OPENSSL
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.maxsslconn = atol(args[1]);
850#else
Emeric Brun0914df82012-10-02 18:45:42 +0200851 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200854#endif
855 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200856 else if (!strcmp(args[0], "maxconnrate")) {
857 if (global.cps_lim != 0) {
858 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT;
860 goto out;
861 }
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867 global.cps_lim = atol(args[1]);
868 }
William Lallemandd85f9172012-11-09 17:05:39 +0100869 else if (!strcmp(args[0], "maxcomprate")) {
870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 global.comp_rate_lim = atoi(args[1]) * 1024;
876 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100877 else if (!strcmp(args[0], "maxpipes")) {
878 if (global.maxpipes != 0) {
879 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200880 err_code |= ERR_ALERT;
881 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100882 }
883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100887 }
888 global.maxpipes = atol(args[1]);
889 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100890 else if (!strcmp(args[0], "maxzlibmem")) {
891 if (*(args[1]) == 0) {
892 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
William Lallemande3a7d992012-11-20 11:25:20 +0100896 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100898 else if (!strcmp(args[0], "maxcompcpuusage")) {
899 if (*(args[1]) == 0) {
900 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 compress_min_idle = 100 - atoi(args[1]);
905 if (compress_min_idle < 0 || compress_min_idle > 100) {
906 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910}
911
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912 else if (!strcmp(args[0], "ulimit-n")) {
913 if (global.rlimit_nofile != 0) {
914 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 err_code |= ERR_ALERT;
916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 }
918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 }
923 global.rlimit_nofile = atol(args[1]);
924 }
925 else if (!strcmp(args[0], "chroot")) {
926 if (global.chroot != NULL) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200928 err_code |= ERR_ALERT;
929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 global.chroot = strdup(args[1]);
937 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200938 else if (!strcmp(args[0], "description")) {
939 int i, len=0;
940 char *d;
941
942 if (!*args[1]) {
943 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
944 file, linenum, args[0]);
945 err_code |= ERR_ALERT | ERR_FATAL;
946 goto out;
947 }
948
949 for(i=1; *args[i]; i++)
950 len += strlen(args[i])+1;
951
952 if (global.desc)
953 free(global.desc);
954
955 global.desc = d = (char *)calloc(1, len);
956
957 d += sprintf(d, "%s", args[1]);
958 for(i=2; *args[i]; i++)
959 d += sprintf(d, " %s", args[i]);
960 }
961 else if (!strcmp(args[0], "node")) {
962 int i;
963 char c;
964
965 for (i=0; args[1][i]; i++) {
966 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100967 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
968 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200969 break;
970 }
971
972 if (!i || args[1][i]) {
973 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
974 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
975 file, linenum, args[0]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979
980 if (global.node)
981 free(global.node);
982
983 global.node = strdup(args[1]);
984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 else if (!strcmp(args[0], "pidfile")) {
986 if (global.pidfile != NULL) {
987 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200988 err_code |= ERR_ALERT;
989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 }
991 if (*(args[1]) == 0) {
992 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200993 err_code |= ERR_ALERT | ERR_FATAL;
994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 }
996 global.pidfile = strdup(args[1]);
997 }
Emeric Bruned760922010-10-22 17:59:25 +0200998 else if (!strcmp(args[0], "unix-bind")) {
999 int cur_arg = 1;
1000 while (*(args[cur_arg])) {
1001 if (!strcmp(args[cur_arg], "prefix")) {
1002 if (global.unix_bind.prefix != NULL) {
1003 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1004 err_code |= ERR_ALERT;
1005 cur_arg += 2;
1006 continue;
1007 }
1008
1009 if (*(args[cur_arg+1]) == 0) {
1010 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1015 cur_arg += 2;
1016 continue;
1017 }
1018
1019 if (!strcmp(args[cur_arg], "mode")) {
1020
1021 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "uid")) {
1027
1028 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "gid")) {
1034
1035 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "user")) {
1041 struct passwd *user;
1042
1043 user = getpwnam(args[cur_arg + 1]);
1044 if (!user) {
1045 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1046 file, linenum, args[0], args[cur_arg + 1 ]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050
1051 global.unix_bind.ux.uid = user->pw_uid;
1052 cur_arg += 2;
1053 continue;
1054 }
1055
1056 if (!strcmp(args[cur_arg], "group")) {
1057 struct group *group;
1058
1059 group = getgrnam(args[cur_arg + 1]);
1060 if (!group) {
1061 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1062 file, linenum, args[0], args[cur_arg + 1 ]);
1063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
1065 }
1066
1067 global.unix_bind.ux.gid = group->gr_gid;
1068 cur_arg += 2;
1069 continue;
1070 }
1071
Willy Tarreaub48f9582011-09-05 01:17:06 +02001072 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001073 file, linenum, args[0]);
1074 err_code |= ERR_ALERT | ERR_FATAL;
1075 goto out;
1076 }
1077 }
William Lallemand0f99e342011-10-12 17:50:54 +02001078 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1079 /* delete previous herited or defined syslog servers */
1080 struct logsrv *back;
1081 struct logsrv *tmp;
1082
1083 if (*(args[1]) != 0) {
1084 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto out;
1087 }
1088
1089 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1090 LIST_DEL(&tmp->list);
1091 free(tmp);
1092 }
1093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001095 struct logsrv *logsrv;
1096
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 if (*(args[1]) == 0 || *(args[2]) == 0) {
1098 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001099 err_code |= ERR_ALERT | ERR_FATAL;
1100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 }
William Lallemand0f99e342011-10-12 17:50:54 +02001102
1103 logsrv = calloc(1, sizeof(struct logsrv));
1104
1105 logsrv->facility = get_log_facility(args[2]);
1106 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001109 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
1111
William Lallemand0f99e342011-10-12 17:50:54 +02001112 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001114 logsrv->level = get_log_level(args[3]);
1115 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120 }
1121
William Lallemand0f99e342011-10-12 17:50:54 +02001122 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001123 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001124 logsrv->minlvl = get_log_level(args[4]);
1125 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001126 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001128 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001129 }
1130 }
1131
Robert Tsai81ae1952007-12-05 10:47:29 +01001132 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001133 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001134 if (!sk) {
1135 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001136 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001137 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001138 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001139 goto out;
1140 }
William Lallemand0f99e342011-10-12 17:50:54 +02001141 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001142 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001143 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001144 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001145 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1146 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001147 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001148 goto out;
1149 }
William Lallemand0f99e342011-10-12 17:50:54 +02001150 logsrv->addr = *sk;
1151 if (!get_host_port(&logsrv->addr))
1152 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154
William Lallemand0f99e342011-10-12 17:50:54 +02001155 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001156 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001157 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1158 char *name;
1159 int len;
1160
1161 if (global.log_send_hostname != NULL) {
1162 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1163 err_code |= ERR_ALERT;
1164 goto out;
1165 }
1166
1167 if (*(args[1]))
1168 name = args[1];
1169 else
1170 name = hostname;
1171
1172 len = strlen(name);
1173
1174 /* We'll add a space after the name to respect the log format */
1175 free(global.log_send_hostname);
1176 global.log_send_hostname = malloc(len + 2);
1177 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1178 }
Kevinm48936af2010-12-22 16:08:21 +00001179 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1180 if (*(args[1]) == 0) {
1181 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185 free(global.log_tag);
1186 global.log_tag = strdup(args[1]);
1187 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001188 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1189 if (global.spread_checks != 0) {
1190 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT;
1192 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001193 }
1194 if (*(args[1]) == 0) {
1195 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001198 }
1199 global.spread_checks = atol(args[1]);
1200 if (global.spread_checks < 0 || global.spread_checks > 50) {
1201 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001202 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001203 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001205 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1206#ifdef USE_CPU_AFFINITY
1207 int cur_arg, i;
1208 unsigned int proc = 0;
1209 unsigned long cpus = 0;
1210
1211 if (strcmp(args[1], "all") == 0)
1212 proc = 0xFFFFFFFF;
1213 else if (strcmp(args[1], "odd") == 0)
1214 proc = 0x55555555;
1215 else if (strcmp(args[1], "even") == 0)
1216 proc = 0xAAAAAAAA;
1217 else {
1218 proc = atoi(args[1]);
1219 if (proc >= 1 && proc <= 32)
1220 proc = 1 << (proc - 1);
1221 }
1222
1223 if (!proc || !*args[2]) {
1224 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1225 file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229
1230 cur_arg = 2;
1231 while (*args[cur_arg]) {
1232 unsigned int low, high;
1233
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001234 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001235 char *dash = strchr(args[cur_arg], '-');
1236
1237 low = high = str2uic(args[cur_arg]);
1238 if (dash)
1239 high = str2uic(dash + 1);
1240
1241 if (high < low) {
1242 unsigned int swap = low;
1243 low = high;
1244 high = swap;
1245 }
1246
1247 if (low < 0 || high >= sizeof(long) * 8) {
1248 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1249 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253
1254 while (low <= high)
1255 cpus |= 1UL << low++;
1256 }
1257 else {
1258 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1259 file, linenum, args[0], args[cur_arg]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 cur_arg++;
1264 }
1265 for (i = 0; i < 32; i++)
1266 if (proc & (1 << i))
1267 global.cpu_map[i] = cpus;
1268#else
1269 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
1272#endif
1273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001275 struct cfg_kw_list *kwl;
1276 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001277 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001278
1279 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1280 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1281 if (kwl->kw[index].section != CFG_GLOBAL)
1282 continue;
1283 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001284 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001285 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001286 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001287 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001288 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001289 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001290 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001291 err_code |= ERR_WARN;
1292 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001293 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001294 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001295 }
1296 }
1297 }
1298
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001302
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001304 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001305 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001306}
1307
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001308void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001310 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 defproxy.mode = PR_MODE_TCP;
1312 defproxy.state = PR_STNEW;
1313 defproxy.maxconn = cfg_maxpconn;
1314 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001315
1316 defproxy.defsrv.inter = DEF_CHKINTR;
1317 defproxy.defsrv.fastinter = 0;
1318 defproxy.defsrv.downinter = 0;
1319 defproxy.defsrv.rise = DEF_RISETIME;
1320 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001321 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001322 defproxy.defsrv.maxqueue = 0;
1323 defproxy.defsrv.minconn = 0;
1324 defproxy.defsrv.maxconn = 0;
1325 defproxy.defsrv.slowstart = 0;
1326 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1327 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1328 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329}
1330
Willy Tarreauade5ec42010-01-28 19:33:49 +01001331
1332static int create_cond_regex_rule(const char *file, int line,
1333 struct proxy *px, int dir, int action, int flags,
1334 const char *cmd, const char *reg, const char *repl,
1335 const char **cond_start)
1336{
1337 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001338 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001339 const char *err;
1340 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001341 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001342
1343 if (px == &defproxy) {
1344 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto err;
1347 }
1348
1349 if (*reg == 0) {
1350 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto err;
1353 }
1354
1355 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1356 err_code |= ERR_WARN;
1357
Willy Tarreau5321c422010-01-28 20:35:13 +01001358 if (cond_start &&
1359 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001360 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1361 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1362 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto err;
1365 }
1366 }
1367 else if (cond_start && **cond_start) {
1368 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1369 file, line, cmd, *cond_start);
1370 err_code |= ERR_ALERT | ERR_FATAL;
1371 goto err;
1372 }
1373
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001374 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001375 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001376 else
1377 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001378
Willy Tarreauade5ec42010-01-28 19:33:49 +01001379 preg = calloc(1, sizeof(regex_t));
1380 if (!preg) {
1381 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1382 err_code = ERR_ALERT | ERR_FATAL;
1383 goto err;
1384 }
1385
1386 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1387 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1388 err_code = ERR_ALERT | ERR_FATAL;
1389 goto err;
1390 }
1391
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001392 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001393 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001394 if (repl && err) {
1395 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1396 file, line, cmd, *err);
1397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto err;
1399 }
1400
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001401 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001402 err_code |= ERR_WARN;
1403
Willy Tarreauf4068b62012-05-08 17:37:49 +02001404 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001405 return err_code;
1406 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001407 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001408 free(preg);
1409 return err_code;
1410}
1411
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001413 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001414 * Returns the error code, 0 if OK, or any combination of :
1415 * - ERR_ABORT: must abort ASAP
1416 * - ERR_FATAL: we can continue parsing but not start the service
1417 * - ERR_WARN: a warning has been emitted
1418 * - ERR_ALERT: an alert has been emitted
1419 * Only the two first ones can stop processing, the two others are just
1420 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001422int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1423{
1424 static struct peers *curpeers = NULL;
1425 struct peer *newpeer = NULL;
1426 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001427 struct bind_conf *bind_conf;
1428 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001429 int err_code = 0;
1430
1431 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1432
1433 err = invalid_char(args[1]);
1434 if (err) {
1435 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1436 file, linenum, *err, args[0], args[1]);
1437 err_code |= ERR_ALERT | ERR_FATAL;
1438 }
1439
1440 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1441 /*
1442 * If there are two proxies with the same name only following
1443 * combinations are allowed:
1444 */
1445 if (strcmp(curpeers->id, args[1]) == 0) {
1446 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1447 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1448 err_code |= ERR_WARN;
1449 }
1450 }
1451
1452 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1453 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1454 err_code |= ERR_ALERT | ERR_ABORT;
1455 goto out;
1456 }
1457
1458 curpeers->next = peers;
1459 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001460 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001461 curpeers->conf.line = linenum;
1462 curpeers->last_change = now.tv_sec;
1463 curpeers->id = strdup(args[1]);
1464 }
1465 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1466 char *rport, *raddr;
1467 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001468 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001469 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001470
1471 if (!*args[2]) {
1472 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1473 file, linenum, args[0]);
1474 err_code |= ERR_ALERT | ERR_FATAL;
1475 goto out;
1476 }
1477
1478 err = invalid_char(args[1]);
1479 if (err) {
1480 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1481 file, linenum, *err, args[1]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1487 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1488 err_code |= ERR_ALERT | ERR_ABORT;
1489 goto out;
1490 }
1491
1492 /* the peers are linked backwards first */
1493 curpeers->count++;
1494 newpeer->next = curpeers->remote;
1495 curpeers->remote = newpeer;
1496 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001497 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001498 newpeer->conf.line = linenum;
1499
1500 newpeer->last_change = now.tv_sec;
1501 newpeer->id = strdup(args[1]);
1502
1503 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001504 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001505 if (rport) {
1506 *rport++ = 0;
1507 realport = atol(rport);
1508 }
1509 if (!realport) {
1510 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
Willy Tarreaufab5a432011-03-04 15:31:53 +01001515 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001516 free(raddr);
1517 if (!sk) {
1518 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001523 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001524 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001525 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001526
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001527 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001528 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1529 file, linenum, newpeer->addr.ss_family, args[2]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001534 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001535
1536 if (strcmp(newpeer->id, localpeer) == 0) {
1537 /* Current is local peer, it define a frontend */
1538 newpeer->local = 1;
1539
1540 if (!curpeers->peers_fe) {
1541 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1542 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1543 err_code |= ERR_ALERT | ERR_ABORT;
1544 goto out;
1545 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001546
Willy Tarreau237250c2011-07-29 01:49:03 +02001547 init_new_proxy(curpeers->peers_fe);
1548 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001549
1550 curpeers->peers_fe->last_change = now.tv_sec;
1551 curpeers->peers_fe->id = strdup(args[1]);
1552 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001553 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001554 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1555 curpeers->peers_fe->timeout.connect = 5000;
1556 curpeers->peers_fe->accept = peer_accept;
1557 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001558
1559 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1560
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001561 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1562 if (err_msg && *err_msg) {
1563 indent_msg(&err_msg, 2);
1564 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1565 }
1566 else
1567 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1568 file, linenum, args[0], args[1], args[2]);
1569 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001570 err_code |= ERR_FATAL;
1571 goto out;
1572 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001573
1574 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1575 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1576 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1577 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1578 l->accept = session_accept;
1579 l->handler = process_session;
1580 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1581 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1582 global.maxsock += l->maxconn;
1583 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001584 }
1585 }
1586 } /* neither "peer" nor "peers" */
1587 else if (*args[0] != 0) {
1588 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1589 err_code |= ERR_ALERT | ERR_FATAL;
1590 goto out;
1591 }
1592
1593out:
1594 return err_code;
1595}
1596
1597
Willy Tarreau3842f002009-06-14 11:39:52 +02001598int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599{
1600 static struct proxy *curproxy = NULL;
1601 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001602 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001603 int rc;
1604 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001605 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001606 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001607 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001608 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001609 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610
Willy Tarreau977b8e42006-12-29 14:19:17 +01001611 if (!strcmp(args[0], "listen"))
1612 rc = PR_CAP_LISTEN;
1613 else if (!strcmp(args[0], "frontend"))
1614 rc = PR_CAP_FE | PR_CAP_RS;
1615 else if (!strcmp(args[0], "backend"))
1616 rc = PR_CAP_BE | PR_CAP_RS;
1617 else if (!strcmp(args[0], "ruleset"))
1618 rc = PR_CAP_RS;
1619 else
1620 rc = PR_CAP_NONE;
1621
1622 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 if (!*args[1]) {
1624 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1625 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_ABORT;
1628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001630
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001631 err = invalid_char(args[1]);
1632 if (err) {
1633 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1634 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001635 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001636 }
1637
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001638 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1639 /*
1640 * If there are two proxies with the same name only following
1641 * combinations are allowed:
1642 *
1643 * listen backend frontend ruleset
1644 * listen - - - -
1645 * backend - - OK -
1646 * frontend - OK - -
1647 * ruleset - - - -
1648 */
1649
1650 if (!strcmp(curproxy->id, args[1]) &&
1651 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1652 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001653 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1654 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1655 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001656 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001657 }
1658 }
1659
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1661 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_ALERT | ERR_ABORT;
1663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001665
Willy Tarreau97cb7802010-01-03 20:23:58 +01001666 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 curproxy->next = proxy;
1668 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001669 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001670 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001671 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001673 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674
1675 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001676 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001677 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001678 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001679
Willy Tarreau4348fad2012-09-20 16:48:07 +02001680 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1681
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001682 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1683 if (err_msg && *err_msg) {
1684 indent_msg(&err_msg, 2);
1685 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1686 }
1687 else
1688 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1689 file, linenum, args[0], args[1], args[2]);
1690 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001691 err_code |= ERR_FATAL;
1692 goto out;
1693 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001694
Willy Tarreau4348fad2012-09-20 16:48:07 +02001695 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001696 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 }
1699
1700 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001701 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001702 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001703
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001706 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001707 curproxy->no_options = defproxy.no_options;
1708 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001709 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001710 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001711 curproxy->except_net = defproxy.except_net;
1712 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001713 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001714 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001716 if (defproxy.fwdfor_hdr_len) {
1717 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1718 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1719 }
1720
Willy Tarreaub86db342009-11-30 11:50:16 +01001721 if (defproxy.orgto_hdr_len) {
1722 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1723 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1724 }
1725
Mark Lamourinec2247f02012-01-04 13:02:01 -05001726 if (defproxy.server_id_hdr_len) {
1727 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1728 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1729 }
1730
Willy Tarreau977b8e42006-12-29 14:19:17 +01001731 if (curproxy->cap & PR_CAP_FE) {
1732 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001733 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001734 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001735
1736 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001737 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1738 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001739
1740 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742
Willy Tarreau977b8e42006-12-29 14:19:17 +01001743 if (curproxy->cap & PR_CAP_BE) {
1744 curproxy->fullconn = defproxy.fullconn;
1745 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001747 if (defproxy.check_req) {
1748 curproxy->check_req = calloc(1, defproxy.check_len);
1749 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1750 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001751 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001753 if (defproxy.expect_str) {
1754 curproxy->expect_str = strdup(defproxy.expect_str);
1755 if (defproxy.expect_regex) {
1756 /* note: this regex is known to be valid */
1757 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1758 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1759 }
1760 }
1761
Willy Tarreau67402132012-05-31 20:40:20 +02001762 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763 if (defproxy.cookie_name)
1764 curproxy->cookie_name = strdup(defproxy.cookie_name);
1765 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001766 if (defproxy.cookie_domain)
1767 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001768
Willy Tarreau31936852010-10-06 16:59:56 +02001769 if (defproxy.cookie_maxidle)
1770 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1771
1772 if (defproxy.cookie_maxlife)
1773 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1774
Emeric Brun647caf12009-06-30 17:57:00 +02001775 if (defproxy.rdp_cookie_name)
1776 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1777 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1778
Willy Tarreau01732802007-11-01 22:48:15 +01001779 if (defproxy.url_param_name)
1780 curproxy->url_param_name = strdup(defproxy.url_param_name);
1781 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001782
Benoitaffb4812009-03-25 13:02:10 +01001783 if (defproxy.hh_name)
1784 curproxy->hh_name = strdup(defproxy.hh_name);
1785 curproxy->hh_len = defproxy.hh_len;
1786 curproxy->hh_match_domain = defproxy.hh_match_domain;
1787
Willy Tarreauef9a3602012-12-08 22:29:20 +01001788 if (defproxy.conn_src.iface_name)
1789 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1790 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1791 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001794 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001795 if (defproxy.capture_name)
1796 curproxy->capture_name = strdup(defproxy.capture_name);
1797 curproxy->capture_namelen = defproxy.capture_namelen;
1798 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800
Willy Tarreau977b8e42006-12-29 14:19:17 +01001801 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001802 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001803 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001804 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001805 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001806 curproxy->uri_auth = defproxy.uri_auth;
1807 curproxy->mon_net = defproxy.mon_net;
1808 curproxy->mon_mask = defproxy.mon_mask;
1809 if (defproxy.monitor_uri)
1810 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1811 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001812 if (defproxy.defbe.name)
1813 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001814
1815 /* get either a pointer to the logformat string or a copy of it */
1816 curproxy->logformat_string = defproxy.logformat_string;
1817 if (curproxy->logformat_string &&
1818 curproxy->logformat_string != default_http_log_format &&
1819 curproxy->logformat_string != default_tcp_log_format &&
1820 curproxy->logformat_string != clf_http_log_format)
1821 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001822 }
1823
1824 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001825 curproxy->timeout.connect = defproxy.timeout.connect;
1826 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001827 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001828 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001829 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001830 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001831 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001832 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001833 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001834 }
1835
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001837
1838 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001839 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001840 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001841 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001842 LIST_INIT(&node->list);
1843 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1844 }
1845
Willy Tarreau196729e2012-05-31 19:30:26 +02001846 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1847 if (curproxy->uniqueid_format_string)
1848 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001849
1850 /* copy default header unique id */
1851 if (defproxy.header_unique_id)
1852 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1853
William Lallemand82fe75c2012-10-23 10:25:10 +02001854 /* default compression options */
1855 if (defproxy.comp != NULL) {
1856 curproxy->comp = calloc(1, sizeof(struct comp));
1857 curproxy->comp->algos = defproxy.comp->algos;
1858 curproxy->comp->types = defproxy.comp->types;
1859 }
1860
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001862 curproxy->conf.used_listener_id = EB_ROOT;
1863 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001864
Willy Tarreau93893792009-07-23 13:19:11 +02001865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 }
1867 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1868 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001869 /* FIXME-20070101: we should do this too at the end of the
1870 * config parsing to free all default values.
1871 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001872 free(defproxy.check_req);
1873 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001874 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001875 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001876 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001877 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001878 free(defproxy.capture_name);
1879 free(defproxy.monitor_uri);
1880 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001881 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001882 free(defproxy.fwdfor_hdr_name);
1883 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001884 free(defproxy.orgto_hdr_name);
1885 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001886 free(defproxy.server_id_hdr_name);
1887 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001888 free(defproxy.expect_str);
1889 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001890
Willy Tarreau39b06652012-06-01 10:58:06 +02001891 if (defproxy.logformat_string != default_http_log_format &&
1892 defproxy.logformat_string != default_tcp_log_format &&
1893 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001894 free(defproxy.logformat_string);
1895
1896 free(defproxy.uniqueid_format_string);
1897
Willy Tarreaua534fea2008-08-03 12:19:50 +02001898 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001899 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001900
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 /* we cannot free uri_auth because it might already be used */
1902 init_default_instance();
1903 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001904 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 }
1907 else if (curproxy == NULL) {
1908 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 }
1912
Willy Tarreau977b8e42006-12-29 14:19:17 +01001913
1914 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001916 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001917 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001918 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001919
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 if (curproxy == &defproxy) {
1921 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001925 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001926 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927
Emeric Bruned760922010-10-22 17:59:25 +02001928 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001929 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001934
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001935 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001936 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001937
1938 /* NOTE: the following line might create several listeners if there
1939 * are comma-separated IPs or port ranges. So all further processing
1940 * will have to be applied to all listeners created after last_listen.
1941 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001942 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1943 if (err_msg && *err_msg) {
1944 indent_msg(&err_msg, 2);
1945 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1946 }
1947 else
1948 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1949 file, linenum, args[0], args[1]);
1950 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001951 err_code |= ERR_ALERT | ERR_FATAL;
1952 goto out;
1953 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001954
Willy Tarreau4348fad2012-09-20 16:48:07 +02001955 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1956 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001957 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001958 }
1959
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001960 cur_arg = 2;
1961 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001962 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001963 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001964 char *err;
1965
Willy Tarreau26982662012-09-12 23:17:10 +02001966 kw = bind_find_kw(args[cur_arg]);
1967 if (kw) {
1968 char *err = NULL;
1969 int code;
1970
1971 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001972 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1973 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001974 cur_arg += 1 + kw->skip ;
1975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
1977 }
1978
Willy Tarreau4348fad2012-09-20 16:48:07 +02001979 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001980 err_code |= code;
1981
1982 if (code) {
1983 if (err && *err) {
1984 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001985 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001986 }
1987 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001988 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1989 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001990 if (code & ERR_FATAL) {
1991 free(err);
1992 cur_arg += 1 + kw->skip;
1993 goto out;
1994 }
1995 }
1996 free(err);
1997 cur_arg += 1 + kw->skip;
1998 continue;
1999 }
2000
Willy Tarreau8638f482012-09-18 18:01:17 +02002001 err = NULL;
2002 if (!bind_dumped) {
2003 bind_dump_kws(&err);
2004 indent_msg(&err, 4);
2005 bind_dumped = 1;
2006 }
2007
2008 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2009 file, linenum, args[0], args[1], args[cur_arg],
2010 err ? " Registered keywords :" : "", err ? err : "");
2011 free(err);
2012
Willy Tarreau93893792009-07-23 13:19:11 +02002013 err_code |= ERR_ALERT | ERR_FATAL;
2014 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002015 }
Willy Tarreau93893792009-07-23 13:19:11 +02002016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017 }
2018 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2019 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2020 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2021 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002022 err_code |= ERR_ALERT | ERR_FATAL;
2023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002025 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002027
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 /* flush useless bits */
2029 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002032 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002033 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002035
Willy Tarreau1c47f852006-07-09 08:22:27 +02002036 if (!*args[1]) {
2037 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002041 }
2042
Willy Tarreaua534fea2008-08-03 12:19:50 +02002043 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002044 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002045 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002046 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002047 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2048
Willy Tarreau93893792009-07-23 13:19:11 +02002049 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2052 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2053 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2054 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2055 else {
2056 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_ALERT | ERR_FATAL;
2058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 }
2060 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002061 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002062 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002063
2064 if (curproxy == &defproxy) {
2065 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2066 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_ALERT | ERR_FATAL;
2068 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002069 }
2070
2071 if (!*args[1]) {
2072 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2073 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002076 }
2077
2078 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002079 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002080
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002081 if (curproxy->uuid <= 0) {
2082 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002083 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002084 err_code |= ERR_ALERT | ERR_FATAL;
2085 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002086 }
2087
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002088 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2089 if (node) {
2090 struct proxy *target = container_of(node, struct proxy, conf.id);
2091 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2092 file, linenum, proxy_type_str(curproxy), curproxy->id,
2093 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
2096 }
2097 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002098 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002099 else if (!strcmp(args[0], "description")) {
2100 int i, len=0;
2101 char *d;
2102
Cyril Bonté99ed3272010-01-24 23:29:44 +01002103 if (curproxy == &defproxy) {
2104 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2105 file, linenum, args[0]);
2106 err_code |= ERR_ALERT | ERR_FATAL;
2107 goto out;
2108 }
2109
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002110 if (!*args[1]) {
2111 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2112 file, linenum, args[0]);
2113 return -1;
2114 }
2115
2116 for(i=1; *args[i]; i++)
2117 len += strlen(args[i])+1;
2118
2119 d = (char *)calloc(1, len);
2120 curproxy->desc = d;
2121
2122 d += sprintf(d, "%s", args[1]);
2123 for(i=2; *args[i]; i++)
2124 d += sprintf(d, " %s", args[i]);
2125
2126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002127 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2128 curproxy->state = PR_STSTOPPED;
2129 }
2130 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2131 curproxy->state = PR_STNEW;
2132 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002133 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2134 int cur_arg = 1;
2135 unsigned int set = 0;
2136
2137 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002138 unsigned int low, high;
2139
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002140 if (strcmp(args[cur_arg], "all") == 0) {
2141 set = 0;
2142 break;
2143 }
2144 else if (strcmp(args[cur_arg], "odd") == 0) {
2145 set |= 0x55555555;
2146 }
2147 else if (strcmp(args[cur_arg], "even") == 0) {
2148 set |= 0xAAAAAAAA;
2149 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002150 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002151 char *dash = strchr(args[cur_arg], '-');
2152
2153 low = high = str2uic(args[cur_arg]);
2154 if (dash)
2155 high = str2uic(dash + 1);
2156
2157 if (high < low) {
2158 unsigned int swap = low;
2159 low = high;
2160 high = swap;
2161 }
2162
2163 if (low < 1 || high > 32) {
2164 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002165 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002168 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002169
2170 if (high > global.nbproc) {
2171 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2172 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002173 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002174 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002175 while (low <= high)
2176 set |= 1 << (low++ - 1);
2177 }
2178 else {
2179 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2180 file, linenum, args[0]);
2181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002183 }
2184 cur_arg++;
2185 }
2186 curproxy->bind_proc = set;
2187 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002188 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002189 if (curproxy == &defproxy) {
2190 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002193 }
2194
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002195 err = invalid_char(args[1]);
2196 if (err) {
2197 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2198 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002200 }
2201
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002202 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2203 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2204 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002207 }
2208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2210 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211
Willy Tarreau977b8e42006-12-29 14:19:17 +01002212 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002213 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002214
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 if (*(args[1]) == 0) {
2216 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2217 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002221
Willy Tarreau67402132012-05-31 20:40:20 +02002222 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002223 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002224 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002225 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 curproxy->cookie_name = strdup(args[1]);
2227 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002228
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 cur_arg = 2;
2230 while (*(args[cur_arg])) {
2231 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002232 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 }
2234 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002235 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 }
2237 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002238 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 }
2240 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002241 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 }
2243 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002244 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002246 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002247 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002250 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002252 else if (!strcmp(args[cur_arg], "httponly")) {
2253 curproxy->ck_opts |= PR_CK_HTTPONLY;
2254 }
2255 else if (!strcmp(args[cur_arg], "secure")) {
2256 curproxy->ck_opts |= PR_CK_SECURE;
2257 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002258 else if (!strcmp(args[cur_arg], "domain")) {
2259 if (!*args[cur_arg + 1]) {
2260 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2261 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002264 }
2265
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002266 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002267 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002268 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2269 " dots nor does not start with a dot."
2270 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002271 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002272 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002273 }
2274
2275 err = invalid_domainchar(args[cur_arg + 1]);
2276 if (err) {
2277 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2278 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002281 }
2282
Willy Tarreau68a897b2009-12-03 23:28:34 +01002283 if (!curproxy->cookie_domain) {
2284 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2285 } else {
2286 /* one domain was already specified, add another one by
2287 * building the string which will be returned along with
2288 * the cookie.
2289 */
2290 char *new_ptr;
2291 int new_len = strlen(curproxy->cookie_domain) +
2292 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2293 new_ptr = malloc(new_len);
2294 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2295 free(curproxy->cookie_domain);
2296 curproxy->cookie_domain = new_ptr;
2297 }
Willy Tarreau31936852010-10-06 16:59:56 +02002298 cur_arg++;
2299 }
2300 else if (!strcmp(args[cur_arg], "maxidle")) {
2301 unsigned int maxidle;
2302 const char *res;
2303
2304 if (!*args[cur_arg + 1]) {
2305 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2306 file, linenum, args[cur_arg]);
2307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
2309 }
2310
2311 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2312 if (res) {
2313 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2314 file, linenum, *res, args[cur_arg]);
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318 curproxy->cookie_maxidle = maxidle;
2319 cur_arg++;
2320 }
2321 else if (!strcmp(args[cur_arg], "maxlife")) {
2322 unsigned int maxlife;
2323 const char *res;
2324
2325 if (!*args[cur_arg + 1]) {
2326 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2327 file, linenum, args[cur_arg]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331
2332 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2333 if (res) {
2334 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2335 file, linenum, *res, args[cur_arg]);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
2339 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002340 cur_arg++;
2341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002343 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 }
2348 cur_arg++;
2349 }
Willy Tarreau67402132012-05-31 20:40:20 +02002350 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2352 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002353 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 }
2355
Willy Tarreau67402132012-05-31 20:40:20 +02002356 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2358 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002361
Willy Tarreau67402132012-05-31 20:40:20 +02002362 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002363 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2364 file, linenum);
2365 err_code |= ERR_ALERT | ERR_FATAL;
2366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002368 else if (!strcmp(args[0], "persist")) { /* persist */
2369 if (*(args[1]) == 0) {
2370 Alert("parsing [%s:%d] : missing persist method.\n",
2371 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002374 }
2375
2376 if (!strncmp(args[1], "rdp-cookie", 10)) {
2377 curproxy->options2 |= PR_O2_RDPC_PRST;
2378
Emeric Brunb982a3d2010-01-04 15:45:53 +01002379 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002380 const char *beg, *end;
2381
2382 beg = args[1] + 11;
2383 end = strchr(beg, ')');
2384
2385 if (!end || end == beg) {
2386 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2387 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002390 }
2391
2392 free(curproxy->rdp_cookie_name);
2393 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2394 curproxy->rdp_cookie_len = end-beg;
2395 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002396 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002397 free(curproxy->rdp_cookie_name);
2398 curproxy->rdp_cookie_name = strdup("msts");
2399 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2400 }
2401 else { /* syntax */
2402 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2403 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002406 }
2407 }
2408 else {
2409 Alert("parsing [%s:%d] : unknown persist method.\n",
2410 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002413 }
2414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002416 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002418 if (curproxy == &defproxy) {
2419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
2422 }
2423
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002426
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002428 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002434 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 curproxy->appsession_name = strdup(args[1]);
2436 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2437 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002438 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2439 if (err) {
2440 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2441 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002444 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002445 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002446
Willy Tarreau51041c72007-09-09 21:56:53 +02002447 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2448 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002449 err_code |= ERR_ALERT | ERR_ABORT;
2450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002452
2453 cur_arg = 6;
2454 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002455 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2456 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002457 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002458 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002459 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002460 } else if (!strcmp(args[cur_arg], "prefix")) {
2461 curproxy->options2 |= PR_O2_AS_PFX;
2462 } else if (!strcmp(args[cur_arg], "mode")) {
2463 if (!*args[cur_arg + 1]) {
2464 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2465 file, linenum, args[0], args[cur_arg]);
2466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
2469
2470 cur_arg++;
2471 if (!strcmp(args[cur_arg], "query-string")) {
2472 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2473 curproxy->options2 |= PR_O2_AS_M_QS;
2474 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2475 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2476 curproxy->options2 |= PR_O2_AS_M_PP;
2477 } else {
2478 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2479 err_code |= ERR_ALERT | ERR_FATAL;
2480 goto out;
2481 }
2482 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002483 cur_arg++;
2484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 } /* Url App Session */
2486 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002487 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002488 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002489
Willy Tarreaubaaee002006-06-26 02:48:02 +02002490 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002491 if (curproxy == &defproxy) {
2492 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 if (*(args[4]) == 0) {
2498 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2499 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002503 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 curproxy->capture_name = strdup(args[2]);
2505 curproxy->capture_namelen = strlen(curproxy->capture_name);
2506 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 curproxy->to_log |= LW_COOKIE;
2508 }
2509 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2510 struct cap_hdr *hdr;
2511
2512 if (curproxy == &defproxy) {
2513 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 }
2517
2518 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2519 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2520 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
2524
2525 hdr = calloc(sizeof(struct cap_hdr), 1);
2526 hdr->next = curproxy->req_cap;
2527 hdr->name = strdup(args[3]);
2528 hdr->namelen = strlen(args[3]);
2529 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002530 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 hdr->index = curproxy->nb_req_cap++;
2532 curproxy->req_cap = hdr;
2533 curproxy->to_log |= LW_REQHDR;
2534 }
2535 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2536 struct cap_hdr *hdr;
2537
2538 if (curproxy == &defproxy) {
2539 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 }
2543
2544 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2545 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2546 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 }
2550 hdr = calloc(sizeof(struct cap_hdr), 1);
2551 hdr->next = curproxy->rsp_cap;
2552 hdr->name = strdup(args[3]);
2553 hdr->namelen = strlen(args[3]);
2554 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002555 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 hdr->index = curproxy->nb_rsp_cap++;
2557 curproxy->rsp_cap = hdr;
2558 curproxy->to_log |= LW_RSPHDR;
2559 }
2560 else {
2561 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2562 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 }
2566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002568 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002570
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 if (*(args[1]) == 0) {
2572 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2573 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 }
2577 curproxy->conn_retries = atol(args[1]);
2578 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002579 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002580 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002581
2582 if (curproxy == &defproxy) {
2583 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
2586 }
2587
Willy Tarreau20b0de52012-12-24 15:45:22 +01002588 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2589 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2590 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2591 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2592 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2593 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002594 file, linenum, args[0]);
2595 err_code |= ERR_WARN;
2596 }
2597
Willy Tarreauff011f22011-01-06 17:51:27 +01002598 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002599
Willy Tarreauff011f22011-01-06 17:51:27 +01002600 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002601 err_code |= ERR_ALERT | ERR_ABORT;
2602 goto out;
2603 }
2604
Willy Tarreauff011f22011-01-06 17:51:27 +01002605 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2606 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002607 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002608 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2609 /* set the header name and length into the proxy structure */
2610 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2611 err_code |= ERR_WARN;
2612
2613 if (!*args[1]) {
2614 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2615 file, linenum, args[0]);
2616 err_code |= ERR_ALERT | ERR_FATAL;
2617 goto out;
2618 }
2619
2620 /* set the desired header name */
2621 free(curproxy->server_id_hdr_name);
2622 curproxy->server_id_hdr_name = strdup(args[1]);
2623 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2624 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002625 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002626 if (curproxy == &defproxy) {
2627 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002630 }
2631
Willy Tarreauef6494c2010-01-28 17:12:36 +01002632 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002633 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2634 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002637 }
2638
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002639 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2640 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2641 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002644 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002645
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002646 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002647 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002648 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002649 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002650 struct redirect_rule *rule;
2651 int cur_arg;
2652 int type = REDIRECT_TYPE_NONE;
2653 int code = 302;
2654 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002655 char *cookie = NULL;
2656 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002657 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002658
Cyril Bonté99ed3272010-01-24 23:29:44 +01002659 if (curproxy == &defproxy) {
2660 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002665 cur_arg = 1;
2666 while (*(args[cur_arg])) {
2667 if (!strcmp(args[cur_arg], "location")) {
2668 if (!*args[cur_arg + 1]) {
2669 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2670 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002673 }
2674
2675 type = REDIRECT_TYPE_LOCATION;
2676 cur_arg++;
2677 destination = args[cur_arg];
2678 }
2679 else if (!strcmp(args[cur_arg], "prefix")) {
2680 if (!*args[cur_arg + 1]) {
2681 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2682 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002685 }
2686
2687 type = REDIRECT_TYPE_PREFIX;
2688 cur_arg++;
2689 destination = args[cur_arg];
2690 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002691 else if (!strcmp(args[cur_arg], "scheme")) {
2692 if (!*args[cur_arg + 1]) {
2693 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2694 file, linenum, args[0], args[cur_arg]);
2695 err_code |= ERR_ALERT | ERR_FATAL;
2696 goto out;
2697 }
2698
2699 type = REDIRECT_TYPE_SCHEME;
2700 cur_arg++;
2701 destination = args[cur_arg];
2702 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002703 else if (!strcmp(args[cur_arg], "set-cookie")) {
2704 if (!*args[cur_arg + 1]) {
2705 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2706 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002707 err_code |= ERR_ALERT | ERR_FATAL;
2708 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002709 }
2710
2711 cur_arg++;
2712 cookie = args[cur_arg];
2713 cookie_set = 1;
2714 }
2715 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2716 if (!*args[cur_arg + 1]) {
2717 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2718 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002721 }
2722
2723 cur_arg++;
2724 cookie = args[cur_arg];
2725 cookie_set = 0;
2726 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002727 else if (!strcmp(args[cur_arg],"code")) {
2728 if (!*args[cur_arg + 1]) {
2729 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2730 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002733 }
2734 cur_arg++;
2735 code = atol(args[cur_arg]);
2736 if (code < 301 || code > 303) {
2737 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2738 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002741 }
2742 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002743 else if (!strcmp(args[cur_arg],"drop-query")) {
2744 flags |= REDIRECT_FLAG_DROP_QS;
2745 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002746 else if (!strcmp(args[cur_arg],"append-slash")) {
2747 flags |= REDIRECT_FLAG_APPEND_SLASH;
2748 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002749 else if (strcmp(args[cur_arg], "if") == 0 ||
2750 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002751 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002752 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002753 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2754 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
2757 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002758 break;
2759 }
2760 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002761 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002762 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002765 }
2766 cur_arg++;
2767 }
2768
2769 if (type == REDIRECT_TYPE_NONE) {
2770 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2771 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002774 }
2775
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002776 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2777 rule->cond = cond;
2778 rule->rdr_str = strdup(destination);
2779 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002780 if (cookie) {
2781 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002782 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002783 */
2784 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002785 if (cookie_set) {
2786 rule->cookie_str = malloc(rule->cookie_len + 10);
2787 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2788 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2789 rule->cookie_len += 9;
2790 } else {
2791 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002792 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002793 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2794 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002795 }
2796 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002797 rule->type = type;
2798 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002799 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002800 LIST_INIT(&rule->list);
2801 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002802 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2803 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002804 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002805 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002806 struct switching_rule *rule;
2807
Willy Tarreaub099aca2008-10-12 17:26:37 +02002808 if (curproxy == &defproxy) {
2809 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002810 err_code |= ERR_ALERT | ERR_FATAL;
2811 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002812 }
2813
Willy Tarreau55ea7572007-06-17 19:56:27 +02002814 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002816
2817 if (*(args[1]) == 0) {
2818 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002819 err_code |= ERR_ALERT | ERR_FATAL;
2820 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002821 }
2822
Willy Tarreauef6494c2010-01-28 17:12:36 +01002823 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002824 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2825 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002828 }
2829
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002830 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2831 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2832 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002835 }
2836
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002837 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002838
Willy Tarreau55ea7572007-06-17 19:56:27 +02002839 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2840 rule->cond = cond;
2841 rule->be.name = strdup(args[1]);
2842 LIST_INIT(&rule->list);
2843 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2844 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002845 else if (strcmp(args[0], "use-server") == 0) {
2846 struct server_rule *rule;
2847
2848 if (curproxy == &defproxy) {
2849 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852 }
2853
2854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2855 err_code |= ERR_WARN;
2856
2857 if (*(args[1]) == 0) {
2858 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
2862
2863 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2864 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2865 file, linenum, args[0]);
2866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
2868 }
2869
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002870 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2871 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2872 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876
2877 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2878
2879 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2880 rule->cond = cond;
2881 rule->srv.name = strdup(args[1]);
2882 LIST_INIT(&rule->list);
2883 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2884 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2885 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002886 else if ((!strcmp(args[0], "force-persist")) ||
2887 (!strcmp(args[0], "ignore-persist"))) {
2888 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002889
2890 if (curproxy == &defproxy) {
2891 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
2894 }
2895
2896 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2897 err_code |= ERR_WARN;
2898
Willy Tarreauef6494c2010-01-28 17:12:36 +01002899 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002900 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2901 file, linenum, args[0]);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002906 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2907 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2908 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
2911 }
2912
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002913 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002914
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002915 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002916 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002917 if (!strcmp(args[0], "force-persist")) {
2918 rule->type = PERSIST_TYPE_FORCE;
2919 } else {
2920 rule->type = PERSIST_TYPE_IGNORE;
2921 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002922 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002923 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002924 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002925 else if (!strcmp(args[0], "stick-table")) {
2926 int myidx = 1;
2927
Emeric Brun32da3c42010-09-23 18:39:19 +02002928 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002929 curproxy->table.type = (unsigned int)-1;
2930 while (*args[myidx]) {
2931 const char *err;
2932
2933 if (strcmp(args[myidx], "size") == 0) {
2934 myidx++;
2935 if (!*(args[myidx])) {
2936 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2937 file, linenum, args[myidx-1]);
2938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
2940 }
2941 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2942 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2943 file, linenum, *err, args[myidx-1]);
2944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
2946 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002947 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002948 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002949 else if (strcmp(args[myidx], "peers") == 0) {
2950 myidx++;
2951 if (!*(args[myidx])) {
2952 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2953 file, linenum, args[myidx-1]);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
2956 }
2957 curproxy->table.peers.name = strdup(args[myidx++]);
2958 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002959 else if (strcmp(args[myidx], "expire") == 0) {
2960 myidx++;
2961 if (!*(args[myidx])) {
2962 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2963 file, linenum, args[myidx-1]);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
2966 }
2967 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2968 if (err) {
2969 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2970 file, linenum, *err, args[myidx-1]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
2974 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002975 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002976 }
2977 else if (strcmp(args[myidx], "nopurge") == 0) {
2978 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002979 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002980 }
2981 else if (strcmp(args[myidx], "type") == 0) {
2982 myidx++;
2983 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2984 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2985 file, linenum, args[myidx]);
2986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
2988 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002989 /* myidx already points to next arg */
2990 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002991 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002992 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002993 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002994
2995 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002996 nw = args[myidx];
2997 while (*nw) {
2998 /* the "store" keyword supports a comma-separated list */
2999 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003000 sa = NULL; /* store arg */
3001 while (*nw && *nw != ',') {
3002 if (*nw == '(') {
3003 *nw = 0;
3004 sa = ++nw;
3005 while (*nw != ')') {
3006 if (!*nw) {
3007 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3008 file, linenum, args[0], cw);
3009 err_code |= ERR_ALERT | ERR_FATAL;
3010 goto out;
3011 }
3012 nw++;
3013 }
3014 *nw = '\0';
3015 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003016 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003017 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003018 if (*nw)
3019 *nw++ = '\0';
3020 type = stktable_get_data_type(cw);
3021 if (type < 0) {
3022 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3023 file, linenum, args[0], cw);
3024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026 }
Willy Tarreauac782882010-06-20 10:41:54 +02003027
3028 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3029 switch (err) {
3030 case PE_NONE: break;
3031 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003032 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3033 file, linenum, args[0], cw);
3034 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003035 break;
3036
3037 case PE_ARG_MISSING:
3038 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3039 file, linenum, args[0], cw);
3040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
3042
3043 case PE_ARG_NOT_USED:
3044 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3045 file, linenum, args[0], cw);
3046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
3048
3049 default:
3050 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3051 file, linenum, args[0], cw);
3052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003054 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003055 }
3056 myidx++;
3057 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003058 else {
3059 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3060 file, linenum, args[myidx]);
3061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003063 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003064 }
3065
3066 if (!curproxy->table.size) {
3067 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3068 file, linenum);
3069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
3071 }
3072
3073 if (curproxy->table.type == (unsigned int)-1) {
3074 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3075 file, linenum);
3076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
3078 }
3079 }
3080 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003081 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003082 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003083 int myidx = 0;
3084 const char *name = NULL;
3085 int flags;
3086
3087 if (curproxy == &defproxy) {
3088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092
3093 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3094 err_code |= ERR_WARN;
3095 goto out;
3096 }
3097
3098 myidx++;
3099 if ((strcmp(args[myidx], "store") == 0) ||
3100 (strcmp(args[myidx], "store-request") == 0)) {
3101 myidx++;
3102 flags = STK_IS_STORE;
3103 }
3104 else if (strcmp(args[myidx], "store-response") == 0) {
3105 myidx++;
3106 flags = STK_IS_STORE | STK_ON_RSP;
3107 }
3108 else if (strcmp(args[myidx], "match") == 0) {
3109 myidx++;
3110 flags = STK_IS_MATCH;
3111 }
3112 else if (strcmp(args[myidx], "on") == 0) {
3113 myidx++;
3114 flags = STK_IS_MATCH | STK_IS_STORE;
3115 }
3116 else {
3117 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
3120 }
3121
3122 if (*(args[myidx]) == 0) {
3123 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
3127
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003128 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003129 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003130 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
3133 }
3134
3135 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003136 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003137 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3138 file, linenum, args[0], expr->fetch->kw);
3139 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003140 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003141 goto out;
3142 }
3143 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003144 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003145 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3146 file, linenum, args[0], expr->fetch->kw);
3147 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003148 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003149 goto out;
3150 }
3151 }
3152
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003153 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3154 if (expr->fetch->cap & SMP_CAP_L7)
3155 curproxy->acl_requires |= ACL_USE_L7_ANY;
3156
Emeric Brunb982a3d2010-01-04 15:45:53 +01003157 if (strcmp(args[myidx], "table") == 0) {
3158 myidx++;
3159 name = args[myidx++];
3160 }
3161
Willy Tarreauef6494c2010-01-28 17:12:36 +01003162 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003163 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3164 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3165 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003166 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003167 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003168 goto out;
3169 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003170 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003171 else if (*(args[myidx])) {
3172 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3173 file, linenum, args[0], args[myidx]);
3174 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003175 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003176 goto out;
3177 }
Emeric Brun97679e72010-09-23 17:56:44 +02003178 if (flags & STK_ON_RSP)
3179 err_code |= warnif_cond_requires_req(cond, file, linenum);
3180 else
3181 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003182
Emeric Brunb982a3d2010-01-04 15:45:53 +01003183 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3184 rule->cond = cond;
3185 rule->expr = expr;
3186 rule->flags = flags;
3187 rule->table.name = name ? strdup(name) : NULL;
3188 LIST_INIT(&rule->list);
3189 if (flags & STK_ON_RSP)
3190 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3191 else
3192 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3193 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003195 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003197
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3199 curproxy->uri_auth = NULL; /* we must detach from the default config */
3200
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003201 if (!*args[1]) {
3202 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003203 } else if (!strcmp(args[1], "admin")) {
3204 struct stats_admin_rule *rule;
3205
3206 if (curproxy == &defproxy) {
3207 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
3210 }
3211
3212 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3213 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3214 err_code |= ERR_ALERT | ERR_ABORT;
3215 goto out;
3216 }
3217
3218 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3219 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3220 file, linenum, args[0], args[1]);
3221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
3223 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003224 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3225 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3226 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
3229 }
3230
3231 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3232
3233 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3234 rule->cond = cond;
3235 LIST_INIT(&rule->list);
3236 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 } else if (!strcmp(args[1], "uri")) {
3238 if (*(args[2]) == 0) {
3239 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_ALERT | ERR_FATAL;
3241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3243 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_ABORT;
3245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 }
3247 } else if (!strcmp(args[1], "realm")) {
3248 if (*(args[2]) == 0) {
3249 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3253 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_ABORT;
3255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003257 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003258 unsigned interval;
3259
3260 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3261 if (err) {
3262 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3263 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_FATAL;
3265 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003266 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3267 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003268 err_code |= ERR_ALERT | ERR_ABORT;
3269 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003270 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003271 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003272 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003273
3274 if (curproxy == &defproxy) {
3275 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
3278 }
3279
3280 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3281 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3282 err_code |= ERR_ALERT | ERR_ABORT;
3283 goto out;
3284 }
3285
Willy Tarreauff011f22011-01-06 17:51:27 +01003286 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3287 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003288 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3289 file, linenum, args[0]);
3290 err_code |= ERR_WARN;
3291 }
3292
Willy Tarreauff011f22011-01-06 17:51:27 +01003293 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003294
Willy Tarreauff011f22011-01-06 17:51:27 +01003295 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003296 err_code |= ERR_ALERT | ERR_ABORT;
3297 goto out;
3298 }
3299
Willy Tarreauff011f22011-01-06 17:51:27 +01003300 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3301 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003302
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 } else if (!strcmp(args[1], "auth")) {
3304 if (*(args[2]) == 0) {
3305 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3309 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_ABORT;
3311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 }
3313 } else if (!strcmp(args[1], "scope")) {
3314 if (*(args[2]) == 0) {
3315 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_FATAL;
3317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_ABORT;
3321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 }
3323 } else if (!strcmp(args[1], "enable")) {
3324 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3325 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_ALERT | ERR_ABORT;
3327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003329 } else if (!strcmp(args[1], "hide-version")) {
3330 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3331 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_ABORT;
3333 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003334 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003335 } else if (!strcmp(args[1], "show-legends")) {
3336 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3337 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3338 err_code |= ERR_ALERT | ERR_ABORT;
3339 goto out;
3340 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003341 } else if (!strcmp(args[1], "show-node")) {
3342
3343 if (*args[2]) {
3344 int i;
3345 char c;
3346
3347 for (i=0; args[2][i]; i++) {
3348 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003349 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3350 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003351 break;
3352 }
3353
3354 if (!i || args[2][i]) {
3355 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3356 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3357 file, linenum, args[0], args[1]);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
3361 }
3362
3363 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3364 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3365 err_code |= ERR_ALERT | ERR_ABORT;
3366 goto out;
3367 }
3368 } else if (!strcmp(args[1], "show-desc")) {
3369 char *desc = NULL;
3370
3371 if (*args[2]) {
3372 int i, len=0;
3373 char *d;
3374
3375 for(i=2; *args[i]; i++)
3376 len += strlen(args[i])+1;
3377
3378 desc = d = (char *)calloc(1, len);
3379
3380 d += sprintf(d, "%s", args[2]);
3381 for(i=3; *args[i]; i++)
3382 d += sprintf(d, " %s", args[i]);
3383 }
3384
3385 if (!*args[2] && !global.desc)
3386 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3387 file, linenum, args[1]);
3388 else {
3389 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3390 free(desc);
3391 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3392 err_code |= ERR_ALERT | ERR_ABORT;
3393 goto out;
3394 }
3395 free(desc);
3396 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003398stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003399 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 +01003400 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 }
3404 }
3405 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003406 int optnum;
3407
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003408 if (*(args[1]) == '\0') {
3409 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3410 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003414
3415 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3416 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003417 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3418 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3419 file, linenum, cfg_opts[optnum].name);
3420 err_code |= ERR_ALERT | ERR_FATAL;
3421 goto out;
3422 }
Willy Tarreau93893792009-07-23 13:19:11 +02003423 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3424 err_code |= ERR_WARN;
3425 goto out;
3426 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003427
Willy Tarreau3842f002009-06-14 11:39:52 +02003428 curproxy->no_options &= ~cfg_opts[optnum].val;
3429 curproxy->options &= ~cfg_opts[optnum].val;
3430
3431 switch (kwm) {
3432 case KWM_STD:
3433 curproxy->options |= cfg_opts[optnum].val;
3434 break;
3435 case KWM_NO:
3436 curproxy->no_options |= cfg_opts[optnum].val;
3437 break;
3438 case KWM_DEF: /* already cleared */
3439 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003440 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003441
Willy Tarreau93893792009-07-23 13:19:11 +02003442 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003443 }
3444 }
3445
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003446 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3447 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003448 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3449 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3450 file, linenum, cfg_opts2[optnum].name);
3451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
3453 }
Willy Tarreau93893792009-07-23 13:19:11 +02003454 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3455 err_code |= ERR_WARN;
3456 goto out;
3457 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003458
Willy Tarreau3842f002009-06-14 11:39:52 +02003459 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3460 curproxy->options2 &= ~cfg_opts2[optnum].val;
3461
3462 switch (kwm) {
3463 case KWM_STD:
3464 curproxy->options2 |= cfg_opts2[optnum].val;
3465 break;
3466 case KWM_NO:
3467 curproxy->no_options2 |= cfg_opts2[optnum].val;
3468 break;
3469 case KWM_DEF: /* already cleared */
3470 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003471 }
Willy Tarreau93893792009-07-23 13:19:11 +02003472 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003473 }
3474 }
3475
Willy Tarreau3842f002009-06-14 11:39:52 +02003476 if (kwm != KWM_STD) {
3477 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003478 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003481 }
3482
Emeric Brun3a058f32009-06-30 18:26:00 +02003483 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003484 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003485 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003486 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003487 if (*(args[2]) != '\0') {
3488 if (!strcmp(args[2], "clf")) {
3489 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003490 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003491 } else {
3492 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003495 }
3496 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003497 if (curproxy->logformat_string != default_http_log_format &&
3498 curproxy->logformat_string != default_tcp_log_format &&
3499 curproxy->logformat_string != clf_http_log_format)
3500 free(curproxy->logformat_string);
3501 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003502 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003503 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003505 if (curproxy->logformat_string != default_http_log_format &&
3506 curproxy->logformat_string != default_tcp_log_format &&
3507 curproxy->logformat_string != clf_http_log_format)
3508 free(curproxy->logformat_string);
3509 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003511 else if (!strcmp(args[1], "tcpka")) {
3512 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003513 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003514 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003515
3516 if (curproxy->cap & PR_CAP_FE)
3517 curproxy->options |= PR_O_TCP_CLI_KA;
3518 if (curproxy->cap & PR_CAP_BE)
3519 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 }
3521 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003522 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_WARN;
3524
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003526 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003527 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003528 curproxy->options2 &= ~PR_O2_CHK_ANY;
3529 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 if (!*args[2]) { /* no argument */
3531 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3532 curproxy->check_len = strlen(DEF_CHECK_REQ);
3533 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003534 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 curproxy->check_req = (char *)malloc(reqlen);
3536 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003537 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003539 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 if (*args[4])
3541 reqlen += strlen(args[4]);
3542 else
3543 reqlen += strlen("HTTP/1.0");
3544
3545 curproxy->check_req = (char *)malloc(reqlen);
3546 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003547 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003549 }
3550 else if (!strcmp(args[1], "ssl-hello-chk")) {
3551 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003552 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003554
Willy Tarreaua534fea2008-08-03 12:19:50 +02003555 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003556 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003557 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003558 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 }
Willy Tarreau23677902007-05-08 23:50:35 +02003560 else if (!strcmp(args[1], "smtpchk")) {
3561 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003562 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003563 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003564 curproxy->options2 &= ~PR_O2_CHK_ANY;
3565 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003566
3567 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3568 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3569 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3570 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3571 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3572 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3573 curproxy->check_req = (char *)malloc(reqlen);
3574 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3575 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3576 } else {
3577 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3578 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3579 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3580 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3581 }
3582 }
3583 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003584 else if (!strcmp(args[1], "pgsql-check")) {
3585 /* use PostgreSQL request to check servers' health */
3586 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3587 err_code |= ERR_WARN;
3588
3589 free(curproxy->check_req);
3590 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003591 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003592 curproxy->options2 |= PR_O2_PGSQL_CHK;
3593
3594 if (*(args[2])) {
3595 int cur_arg = 2;
3596
3597 while (*(args[cur_arg])) {
3598 if (strcmp(args[cur_arg], "user") == 0) {
3599 char * packet;
3600 uint32_t packet_len;
3601 uint32_t pv;
3602
3603 /* suboption header - needs additional argument for it */
3604 if (*(args[cur_arg+1]) == 0) {
3605 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3606 file, linenum, args[0], args[1], args[cur_arg]);
3607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
3609 }
3610
3611 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3612 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3613 pv = htonl(0x30000); /* protocol version 3.0 */
3614
3615 packet = (char*) calloc(1, packet_len);
3616
3617 memcpy(packet + 4, &pv, 4);
3618
3619 /* copy "user" */
3620 memcpy(packet + 8, "user", 4);
3621
3622 /* copy username */
3623 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3624
3625 free(curproxy->check_req);
3626 curproxy->check_req = packet;
3627 curproxy->check_len = packet_len;
3628
3629 packet_len = htonl(packet_len);
3630 memcpy(packet, &packet_len, 4);
3631 cur_arg += 2;
3632 } else {
3633 /* unknown suboption - catchall */
3634 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3635 file, linenum, args[0], args[1]);
3636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
3638 }
3639 } /* end while loop */
3640 }
3641 }
3642
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003643 else if (!strcmp(args[1], "redis-check")) {
3644 /* use REDIS PING request to check servers' health */
3645 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3646 err_code |= ERR_WARN;
3647
3648 free(curproxy->check_req);
3649 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003650 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003651 curproxy->options2 |= PR_O2_REDIS_CHK;
3652
3653 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3654 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3655 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3656 }
3657
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003658 else if (!strcmp(args[1], "mysql-check")) {
3659 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003660 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3661 err_code |= ERR_WARN;
3662
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003663 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003664 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003665 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003666 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003667
3668 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3669 * const char mysql40_client_auth_pkt[] = {
3670 * "\x0e\x00\x00" // packet length
3671 * "\x01" // packet number
3672 * "\x00\x00" // client capabilities
3673 * "\x00\x00\x01" // max packet
3674 * "haproxy\x00" // username (null terminated string)
3675 * "\x00" // filler (always 0x00)
3676 * "\x01\x00\x00" // packet length
3677 * "\x00" // packet number
3678 * "\x01" // COM_QUIT command
3679 * };
3680 */
3681
3682 if (*(args[2])) {
3683 int cur_arg = 2;
3684
3685 while (*(args[cur_arg])) {
3686 if (strcmp(args[cur_arg], "user") == 0) {
3687 char *mysqluser;
3688 int packetlen, reqlen, userlen;
3689
3690 /* suboption header - needs additional argument for it */
3691 if (*(args[cur_arg+1]) == 0) {
3692 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3693 file, linenum, args[0], args[1], args[cur_arg]);
3694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
3696 }
3697 mysqluser = args[cur_arg + 1];
3698 userlen = strlen(mysqluser);
3699 packetlen = userlen + 7;
3700 reqlen = packetlen + 9;
3701
3702 free(curproxy->check_req);
3703 curproxy->check_req = (char *)calloc(1, reqlen);
3704 curproxy->check_len = reqlen;
3705
3706 snprintf(curproxy->check_req, 4, "%c%c%c",
3707 ((unsigned char) packetlen & 0xff),
3708 ((unsigned char) (packetlen >> 8) & 0xff),
3709 ((unsigned char) (packetlen >> 16) & 0xff));
3710
3711 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003712 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003713 curproxy->check_req[8] = 1;
3714 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3715 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3716 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3717 cur_arg += 2;
3718 } else {
3719 /* unknown suboption - catchall */
3720 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3721 file, linenum, args[0], args[1]);
3722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
3724 }
3725 } /* end while loop */
3726 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003727 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003728 else if (!strcmp(args[1], "ldap-check")) {
3729 /* use LDAP request to check servers' health */
3730 free(curproxy->check_req);
3731 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003732 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003733 curproxy->options2 |= PR_O2_LDAP_CHK;
3734
3735 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3736 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3737 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3738 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003739 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003740 int cur_arg;
3741
3742 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3743 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003744 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003745
Willy Tarreau87cf5142011-08-19 22:57:24 +02003746 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003747
3748 free(curproxy->fwdfor_hdr_name);
3749 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3750 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3751
3752 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3753 cur_arg = 2;
3754 while (*(args[cur_arg])) {
3755 if (!strcmp(args[cur_arg], "except")) {
3756 /* suboption except - needs additional argument for it */
3757 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3758 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3759 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003762 }
3763 /* flush useless bits */
3764 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003765 cur_arg += 2;
3766 } else if (!strcmp(args[cur_arg], "header")) {
3767 /* suboption header - needs additional argument for it */
3768 if (*(args[cur_arg+1]) == 0) {
3769 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3770 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003773 }
3774 free(curproxy->fwdfor_hdr_name);
3775 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3776 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3777 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003778 } else if (!strcmp(args[cur_arg], "if-none")) {
3779 curproxy->options &= ~PR_O_FF_ALWAYS;
3780 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003781 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003782 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003783 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003784 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003787 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003788 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003789 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003790 else if (!strcmp(args[1], "originalto")) {
3791 int cur_arg;
3792
3793 /* insert x-original-to field, but not for the IP address listed as an except.
3794 * set default options (ie: bitfield, header name, etc)
3795 */
3796
3797 curproxy->options |= PR_O_ORGTO;
3798
3799 free(curproxy->orgto_hdr_name);
3800 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3801 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3802
Willy Tarreau87cf5142011-08-19 22:57:24 +02003803 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003804 cur_arg = 2;
3805 while (*(args[cur_arg])) {
3806 if (!strcmp(args[cur_arg], "except")) {
3807 /* suboption except - needs additional argument for it */
3808 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3809 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3810 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003813 }
3814 /* flush useless bits */
3815 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3816 cur_arg += 2;
3817 } else if (!strcmp(args[cur_arg], "header")) {
3818 /* suboption header - needs additional argument for it */
3819 if (*(args[cur_arg+1]) == 0) {
3820 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3821 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003824 }
3825 free(curproxy->orgto_hdr_name);
3826 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3827 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3828 cur_arg += 2;
3829 } else {
3830 /* unknown suboption - catchall */
3831 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3832 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003835 }
3836 } /* end while loop */
3837 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 else {
3839 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 }
Willy Tarreau93893792009-07-23 13:19:11 +02003843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003845 else if (!strcmp(args[0], "default_backend")) {
3846 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003848
3849 if (*(args[1]) == 0) {
3850 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003853 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003854 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003855 curproxy->defbe.name = strdup(args[1]);
3856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003858 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003860
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003861 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3862 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003863 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 /* enable reconnections to dispatch */
3865 curproxy->options |= PR_O_REDISP;
3866 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003867 else if (!strcmp(args[0], "http-check")) {
3868 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003869 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003870
3871 if (strcmp(args[1], "disable-on-404") == 0) {
3872 /* enable a graceful server shutdown on an HTTP 404 response */
3873 curproxy->options |= PR_O_DISABLE404;
3874 }
Willy Tarreauef781042010-01-27 11:53:01 +01003875 else if (strcmp(args[1], "send-state") == 0) {
3876 /* enable emission of the apparent state of a server in HTTP checks */
3877 curproxy->options2 |= PR_O2_CHK_SNDST;
3878 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003879 else if (strcmp(args[1], "expect") == 0) {
3880 const char *ptr_arg;
3881 int cur_arg;
3882
3883 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3884 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
3887 }
3888
3889 cur_arg = 2;
3890 /* consider exclamation marks, sole or at the beginning of a word */
3891 while (*(ptr_arg = args[cur_arg])) {
3892 while (*ptr_arg == '!') {
3893 curproxy->options2 ^= PR_O2_EXP_INV;
3894 ptr_arg++;
3895 }
3896 if (*ptr_arg)
3897 break;
3898 cur_arg++;
3899 }
3900 /* now ptr_arg points to the beginning of a word past any possible
3901 * exclamation mark, and cur_arg is the argument which holds this word.
3902 */
3903 if (strcmp(ptr_arg, "status") == 0) {
3904 if (!*(args[cur_arg + 1])) {
3905 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3906 file, linenum, args[0], args[1], ptr_arg);
3907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
3909 }
3910 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003911 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003912 curproxy->expect_str = strdup(args[cur_arg + 1]);
3913 }
3914 else if (strcmp(ptr_arg, "string") == 0) {
3915 if (!*(args[cur_arg + 1])) {
3916 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3917 file, linenum, args[0], args[1], ptr_arg);
3918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
3920 }
3921 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003922 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003923 curproxy->expect_str = strdup(args[cur_arg + 1]);
3924 }
3925 else if (strcmp(ptr_arg, "rstatus") == 0) {
3926 if (!*(args[cur_arg + 1])) {
3927 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3928 file, linenum, args[0], args[1], ptr_arg);
3929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
3931 }
3932 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003933 free(curproxy->expect_str);
3934 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3935 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003936 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3937 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3938 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3939 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
3942 }
3943 }
3944 else if (strcmp(ptr_arg, "rstring") == 0) {
3945 if (!*(args[cur_arg + 1])) {
3946 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3947 file, linenum, args[0], args[1], ptr_arg);
3948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
3950 }
3951 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003952 free(curproxy->expect_str);
3953 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3954 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003955 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3956 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3957 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3958 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
3962 }
3963 else {
3964 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3965 file, linenum, args[0], args[1], ptr_arg);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003970 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003971 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 +02003972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003974 }
3975 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003976 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003977 if (curproxy == &defproxy) {
3978 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003981 }
3982
Willy Tarreaub80c2302007-11-30 20:51:32 +01003983 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003985
3986 if (strcmp(args[1], "fail") == 0) {
3987 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003988 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003989 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3990 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003993 }
3994
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003995 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3996 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3997 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004000 }
4001 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4002 }
4003 else {
4004 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004007 }
4008 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009#ifdef TPROXY
4010 else if (!strcmp(args[0], "transparent")) {
4011 /* enable transparent proxy connections */
4012 curproxy->options |= PR_O_TRANSP;
4013 }
4014#endif
4015 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004016 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004017 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004018
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 if (*(args[1]) == 0) {
4020 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 }
4024 curproxy->maxconn = atol(args[1]);
4025 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004026 else if (!strcmp(args[0], "backlog")) { /* backlog */
4027 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004028 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004029
4030 if (*(args[1]) == 0) {
4031 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004034 }
4035 curproxy->backlog = atol(args[1]);
4036 }
Willy Tarreau86034312006-12-29 00:10:33 +01004037 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004038 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004039 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004040
Willy Tarreau86034312006-12-29 00:10:33 +01004041 if (*(args[1]) == 0) {
4042 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004045 }
4046 curproxy->fullconn = atol(args[1]);
4047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4049 if (*(args[1]) == 0) {
4050 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004054 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4055 if (err) {
4056 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4057 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004060 }
4061 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062 }
4063 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004064 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 if (curproxy == &defproxy) {
4066 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004070 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004072
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073 if (strchr(args[1], ':') == NULL) {
4074 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004077 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004078 sk = str2sa(args[1]);
4079 if (!sk) {
4080 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
4084 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004085 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 }
4087 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004089 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004090
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004091 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4092 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004095 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004096 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004097 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4098 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4099 err_code |= ERR_WARN;
4100
4101 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4102 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4103 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4104 }
4105 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4106 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4107 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4108 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004109 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4110 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4111 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4112 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004113 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004114 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
4118 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004119 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004121 char *rport, *raddr;
4122 short realport = 0;
4123 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004124
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004125 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004129 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004130 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004131 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132
4133 if (!*args[2]) {
4134 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4135 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004139
4140 err = invalid_char(args[1]);
4141 if (err) {
4142 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4143 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004146 }
4147
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004148 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004149 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004150
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004151 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4152 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4153 err_code |= ERR_ALERT | ERR_ABORT;
4154 goto out;
4155 }
4156
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004157 /* the servers are linked backwards first */
4158 newsrv->next = curproxy->srv;
4159 curproxy->srv = newsrv;
4160 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004161 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004162 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004164 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004165 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004166 LIST_INIT(&newsrv->pendconns);
4167 do_check = 0;
4168 newsrv->state = SRV_RUNNING; /* early server setup */
4169 newsrv->last_change = now.tv_sec;
4170 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004172 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004173 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004174 * - IP: => port=+0, relative
4175 * - IP:N => port=N, absolute
4176 * - IP:+N => port=+N, relative
4177 * - IP:-N => port=-N, relative
4178 */
4179 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004180 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004181 if (rport) {
4182 *rport++ = 0;
4183 realport = atol(rport);
4184 if (!isdigit((unsigned char)*rport))
4185 newsrv->state |= SRV_MAPPORTS;
4186 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004188
Willy Tarreaufab5a432011-03-04 15:31:53 +01004189 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004190 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004191 if (!sk) {
4192 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
4196 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004197 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4198 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004199
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004200 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004201 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4202 file, linenum, newsrv->addr.ss_family, args[2]);
4203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
4205 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004206 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004207
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004208 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004209 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004210 newsrv->inter = curproxy->defsrv.inter;
4211 newsrv->fastinter = curproxy->defsrv.fastinter;
4212 newsrv->downinter = curproxy->defsrv.downinter;
4213 newsrv->rise = curproxy->defsrv.rise;
4214 newsrv->fall = curproxy->defsrv.fall;
4215 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4216 newsrv->minconn = curproxy->defsrv.minconn;
4217 newsrv->maxconn = curproxy->defsrv.maxconn;
4218 newsrv->slowstart = curproxy->defsrv.slowstart;
4219 newsrv->onerror = curproxy->defsrv.onerror;
4220 newsrv->consecutive_errors_limit
4221 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004222#ifdef OPENSSL
4223 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4224#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004225 newsrv->uweight = newsrv->iweight
4226 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004228 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004230 cur_arg = 3;
4231 } else {
4232 newsrv = &curproxy->defsrv;
4233 cur_arg = 1;
4234 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004235
Willy Tarreaubaaee002006-06-26 02:48:02 +02004236 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004237 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004238 newsrv->cookie = strdup(args[cur_arg + 1]);
4239 newsrv->cklen = strlen(args[cur_arg + 1]);
4240 cur_arg += 2;
4241 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004242 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004243 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4244 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4245 cur_arg += 2;
4246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004247 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004248 if (!*args[cur_arg + 1]) {
4249 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4250 file, linenum, args[cur_arg]);
4251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
4253 }
4254
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004256 if (newsrv->rise <= 0) {
4257 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4258 file, linenum, args[cur_arg]);
4259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
4261 }
4262
Willy Tarreau96839092010-03-29 10:02:24 +02004263 if (newsrv->health)
4264 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004265 cur_arg += 2;
4266 }
4267 else if (!strcmp(args[cur_arg], "fall")) {
4268 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004269
4270 if (!*args[cur_arg + 1]) {
4271 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4272 file, linenum, args[cur_arg]);
4273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
4275 }
4276
4277 if (newsrv->fall <= 0) {
4278 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4279 file, linenum, args[cur_arg]);
4280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
4282 }
4283
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284 cur_arg += 2;
4285 }
4286 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004287 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4288 if (err) {
4289 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4290 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004293 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004294 if (val <= 0) {
4295 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4296 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004299 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004300 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 cur_arg += 2;
4302 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004303 else if (!strcmp(args[cur_arg], "fastinter")) {
4304 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4305 if (err) {
4306 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4307 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004310 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004311 if (val <= 0) {
4312 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4313 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_ALERT | ERR_FATAL;
4315 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004316 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004317 newsrv->fastinter = val;
4318 cur_arg += 2;
4319 }
4320 else if (!strcmp(args[cur_arg], "downinter")) {
4321 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4322 if (err) {
4323 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4324 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004327 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004328 if (val <= 0) {
4329 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4330 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004331 err_code |= ERR_ALERT | ERR_FATAL;
4332 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004333 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004334 newsrv->downinter = val;
4335 cur_arg += 2;
4336 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004337 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004338 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004339 if (!sk) {
4340 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4341 err_code |= ERR_ALERT | ERR_FATAL;
4342 goto out;
4343 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004344 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004345 cur_arg += 2;
4346 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004347 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004348 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349 cur_arg += 2;
4350 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004351 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004352 newsrv->state |= SRV_BACKUP;
4353 cur_arg ++;
4354 }
Simon Hormanfa461682011-06-25 09:39:49 +09004355 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4356 newsrv->state |= SRV_NON_STICK;
4357 cur_arg ++;
4358 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004359 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4360 newsrv->state |= SRV_SEND_PROXY;
4361 cur_arg ++;
4362 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004363 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4364 newsrv->check.send_proxy = 1;
4365 cur_arg ++;
4366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004367 else if (!strcmp(args[cur_arg], "weight")) {
4368 int w;
4369 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004370 if (w < 0 || w > 256) {
4371 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004375 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004376 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 cur_arg += 2;
4378 }
4379 else if (!strcmp(args[cur_arg], "minconn")) {
4380 newsrv->minconn = atol(args[cur_arg + 1]);
4381 cur_arg += 2;
4382 }
4383 else if (!strcmp(args[cur_arg], "maxconn")) {
4384 newsrv->maxconn = atol(args[cur_arg + 1]);
4385 cur_arg += 2;
4386 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004387 else if (!strcmp(args[cur_arg], "maxqueue")) {
4388 newsrv->maxqueue = atol(args[cur_arg + 1]);
4389 cur_arg += 2;
4390 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004391 else if (!strcmp(args[cur_arg], "slowstart")) {
4392 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004393 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004394 if (err) {
4395 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4396 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004399 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004400 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004401 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4402 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004405 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004406 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004407 cur_arg += 2;
4408 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004409 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004410
4411 if (!*args[cur_arg + 1]) {
4412 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4413 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004416 }
4417
4418 newsrv->trackit = strdup(args[cur_arg + 1]);
4419
4420 cur_arg += 2;
4421 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004422 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423 global.maxsock++;
4424 do_check = 1;
4425 cur_arg += 1;
4426 }
Willy Tarreau96839092010-03-29 10:02:24 +02004427 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4428 newsrv->state |= SRV_MAINTAIN;
4429 newsrv->state &= ~SRV_RUNNING;
4430 newsrv->health = 0;
4431 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004432 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004433 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004434 if (!strcmp(args[cur_arg + 1], "none"))
4435 newsrv->observe = HANA_OBS_NONE;
4436 else if (!strcmp(args[cur_arg + 1], "layer4"))
4437 newsrv->observe = HANA_OBS_LAYER4;
4438 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4439 if (curproxy->mode != PR_MODE_HTTP) {
4440 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4441 file, linenum, args[cur_arg + 1]);
4442 err_code |= ERR_ALERT;
4443 }
4444 newsrv->observe = HANA_OBS_LAYER7;
4445 }
4446 else {
4447 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004448 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004449 file, linenum, args[cur_arg], args[cur_arg + 1]);
4450 err_code |= ERR_ALERT | ERR_FATAL;
4451 goto out;
4452 }
4453
4454 cur_arg += 2;
4455 }
4456 else if (!strcmp(args[cur_arg], "on-error")) {
4457 if (!strcmp(args[cur_arg + 1], "fastinter"))
4458 newsrv->onerror = HANA_ONERR_FASTINTER;
4459 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4460 newsrv->onerror = HANA_ONERR_FAILCHK;
4461 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4462 newsrv->onerror = HANA_ONERR_SUDDTH;
4463 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4464 newsrv->onerror = HANA_ONERR_MARKDWN;
4465 else {
4466 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004467 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004468 file, linenum, args[cur_arg], args[cur_arg + 1]);
4469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
4471 }
4472
4473 cur_arg += 2;
4474 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004475 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4476 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4477 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4478 else {
4479 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4480 file, linenum, args[cur_arg], args[cur_arg + 1]);
4481 err_code |= ERR_ALERT | ERR_FATAL;
4482 goto out;
4483 }
4484
4485 cur_arg += 2;
4486 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004487 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4488 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4489 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4490 else {
4491 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4492 file, linenum, args[cur_arg], args[cur_arg + 1]);
4493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
4495 }
4496
4497 cur_arg += 2;
4498 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004499 else if (!strcmp(args[cur_arg], "error-limit")) {
4500 if (!*args[cur_arg + 1]) {
4501 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4502 file, linenum, args[cur_arg]);
4503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
4505 }
4506
4507 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4508
4509 if (newsrv->consecutive_errors_limit <= 0) {
4510 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4511 file, linenum, args[cur_arg]);
4512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
4514 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004515 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004516 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004517 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004518 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004519 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004520
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004522 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4523 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004527 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004528 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4529 if (!sk) {
4530 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4531 err_code |= ERR_ALERT | ERR_FATAL;
4532 goto out;
4533 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004534 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004535
4536 if (port_low != port_high) {
4537 int i;
4538 if (port_low <= 0 || port_low > 65535 ||
4539 port_high <= 0 || port_high > 65535 ||
4540 port_low > port_high) {
4541 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4542 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004545 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004546 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4547 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4548 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004549 }
4550
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004552 while (*(args[cur_arg])) {
4553 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004554#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4555#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004556 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004557 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4558 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004559 err_code |= ERR_ALERT | ERR_FATAL;
4560 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004561 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004562#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004563 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004564 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004565 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004568 }
4569 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004570 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4571 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004572 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004573 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4574 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004575 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4576 char *name, *end;
4577
4578 name = args[cur_arg+1] + 7;
4579 while (isspace(*name))
4580 name++;
4581
4582 end = name;
4583 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4584 end++;
4585
Willy Tarreauef9a3602012-12-08 22:29:20 +01004586 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4587 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4588 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4589 newsrv->conn_src.bind_hdr_len = end - name;
4590 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4591 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4592 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004593
4594 /* now look for an occurrence number */
4595 while (isspace(*end))
4596 end++;
4597 if (*end == ',') {
4598 end++;
4599 name = end;
4600 if (*end == '-')
4601 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004602 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004603 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004604 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004605 }
4606
Willy Tarreauef9a3602012-12-08 22:29:20 +01004607 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004608 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4609 " occurrences values smaller than %d.\n",
4610 file, linenum, MAX_HDR_HISTORY);
4611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
4613 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004614 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004615 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004616 if (!sk) {
4617 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
4620 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004621 newsrv->conn_src.tproxy_addr = *sk;
4622 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004623 }
4624 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004625#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004626 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004627#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004628 cur_arg += 2;
4629 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004630#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004631 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004632 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004635#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4636 } /* "usesrc" */
4637
4638 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4639#ifdef SO_BINDTODEVICE
4640 if (!*args[cur_arg + 1]) {
4641 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4642 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004645 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004646 free(newsrv->conn_src.iface_name);
4647 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4648 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004649 global.last_checks |= LSTCHK_NETADM;
4650#else
4651 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4652 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004655#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004656 cur_arg += 2;
4657 continue;
4658 }
4659 /* this keyword in not an option of "source" */
4660 break;
4661 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004663 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004664 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4665 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004670 static int srv_dumped;
4671 struct srv_kw *kw;
4672 char *err;
4673
4674 kw = srv_find_kw(args[cur_arg]);
4675 if (kw) {
4676 char *err = NULL;
4677 int code;
4678
4679 if (!kw->parse) {
4680 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4681 file, linenum, args[0], args[1], args[cur_arg]);
4682 cur_arg += 1 + kw->skip ;
4683 err_code |= ERR_ALERT | ERR_FATAL;
4684 goto out;
4685 }
4686
4687 if (defsrv && !kw->default_ok) {
4688 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4689 file, linenum, args[0], args[1], args[cur_arg]);
4690 cur_arg += 1 + kw->skip ;
4691 err_code |= ERR_ALERT;
4692 continue;
4693 }
4694
4695 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4696 err_code |= code;
4697
4698 if (code) {
4699 if (err && *err) {
4700 indent_msg(&err, 2);
4701 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4702 }
4703 else
4704 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4705 file, linenum, args[0], args[1], args[cur_arg]);
4706 if (code & ERR_FATAL) {
4707 free(err);
4708 cur_arg += 1 + kw->skip;
4709 goto out;
4710 }
4711 }
4712 free(err);
4713 cur_arg += 1 + kw->skip;
4714 continue;
4715 }
4716
4717 err = NULL;
4718 if (!srv_dumped) {
4719 srv_dump_kws(&err);
4720 indent_msg(&err, 4);
4721 srv_dumped = 1;
4722 }
4723
4724 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4725 file, linenum, args[0], args[1], args[cur_arg],
4726 err ? " Registered keywords :" : "", err ? err : "");
4727 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004728
Willy Tarreau93893792009-07-23 13:19:11 +02004729 err_code |= ERR_ALERT | ERR_FATAL;
4730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 }
4732 }
4733
4734 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004735 if (newsrv->trackit) {
4736 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4737 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004738 err_code |= ERR_ALERT | ERR_FATAL;
4739 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004740 }
4741
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004742 /* If neither a port nor an addr was specified and no check transport
4743 * layer is forced, then the transport layer used by the checks is the
4744 * same as for the production traffic. Otherwise we use raw_sock by
4745 * default, unless one is specified.
4746 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004747 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004748#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004749 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004750#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004751 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4752 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004753 /* try to get the port from check.addr if check.port not set */
4754 if (!newsrv->check.port)
4755 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004756
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004757 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4758 newsrv->check.port = realport; /* by default */
4759 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004760 /* not yet valid, because no port was set on
4761 * the server either. We'll check if we have
4762 * a known port on the first listener.
4763 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004764 struct listener *l;
4765
4766 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004767 newsrv->check.port = get_host_port(&l->addr);
4768 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004769 break;
4770 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004771 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004772 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4774 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004778
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004779 /* Allocate buffer for check requests... */
4780 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004781 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4782 err_code |= ERR_ALERT | ERR_ABORT;
4783 goto out;
4784 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004785 newsrv->check.bi->size = global.tune.chksize;
4786
4787 /* Allocate buffer for check responses... */
4788 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4789 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4790 err_code |= ERR_ALERT | ERR_ABORT;
4791 goto out;
4792 }
4793 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004794
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004795 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004796 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004797 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4798 err_code |= ERR_ALERT | ERR_ABORT;
4799 goto out;
4800 }
4801
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004802 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4803 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804 newsrv->state |= SRV_CHECKED;
4805 }
4806
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004807 if (!defsrv) {
4808 if (newsrv->state & SRV_BACKUP)
4809 curproxy->srv_bck++;
4810 else
4811 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004812
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004813 newsrv->prev_state = newsrv->state;
4814 }
William Lallemanda73203e2012-03-12 12:48:57 +01004815 }
4816
4817 else if (strcmp(args[0], "unique-id-format") == 0) {
4818 if (!*(args[1])) {
4819 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
4822 }
William Lallemand3203ff42012-11-11 17:30:56 +01004823 if (*(args[2])) {
4824 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
4827 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004828 free(curproxy->uniqueid_format_string);
4829 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004830 }
William Lallemanda73203e2012-03-12 12:48:57 +01004831
4832 else if (strcmp(args[0], "unique-id-header") == 0) {
4833 if (!*(args[1])) {
4834 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
4837 }
4838 free(curproxy->header_unique_id);
4839 curproxy->header_unique_id = strdup(args[1]);
4840 }
4841
William Lallemand723b73a2012-02-08 16:37:49 +01004842 else if (strcmp(args[0], "log-format") == 0) {
4843 if (!*(args[1])) {
4844 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
4847 }
William Lallemand3203ff42012-11-11 17:30:56 +01004848 if (*(args[2])) {
4849 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
4852 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004853
4854 if (curproxy->logformat_string != default_http_log_format &&
4855 curproxy->logformat_string != default_tcp_log_format &&
4856 curproxy->logformat_string != clf_http_log_format)
4857 free(curproxy->logformat_string);
4858 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 }
William Lallemand723b73a2012-02-08 16:37:49 +01004860
William Lallemand0f99e342011-10-12 17:50:54 +02004861 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4862 /* delete previous herited or defined syslog servers */
4863 struct logsrv *back;
4864
4865 if (*(args[1]) != 0) {
4866 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4867 err_code |= ERR_ALERT | ERR_FATAL;
4868 goto out;
4869 }
4870
William Lallemand723b73a2012-02-08 16:37:49 +01004871 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4872 LIST_DEL(&tmplogsrv->list);
4873 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004874 }
4875 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004876 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004877 struct logsrv *logsrv;
4878
Willy Tarreaubaaee002006-06-26 02:48:02 +02004879 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004880 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004881 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004882 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004883 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004884 LIST_INIT(&node->list);
4885 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887 }
4888 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004889
4890 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891
William Lallemand0f99e342011-10-12 17:50:54 +02004892 logsrv->facility = get_log_facility(args[2]);
4893 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004895 err_code |= ERR_ALERT | ERR_FATAL;
4896 goto out;
4897
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 }
4899
William Lallemand0f99e342011-10-12 17:50:54 +02004900 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004902 logsrv->level = get_log_level(args[3]);
4903 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
4907
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 }
4909 }
4910
William Lallemand0f99e342011-10-12 17:50:54 +02004911 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004912 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004913 logsrv->minlvl = get_log_level(args[4]);
4914 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004915 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004919 }
4920 }
4921
Robert Tsai81ae1952007-12-05 10:47:29 +01004922 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004923 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004924 if (!sk) {
4925 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004926 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
4929 }
William Lallemand0f99e342011-10-12 17:50:54 +02004930 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004931 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004932 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004933 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004934 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4935 err_code |= ERR_ALERT | ERR_FATAL;
4936 goto out;
4937 }
William Lallemand0f99e342011-10-12 17:50:54 +02004938 logsrv->addr = *sk;
4939 if (!get_host_port(&logsrv->addr))
4940 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 }
William Lallemand0f99e342011-10-12 17:50:54 +02004942
4943 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
4945 else {
4946 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4947 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
4951 }
4952 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004953 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004954 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004955
Willy Tarreau977b8e42006-12-29 14:19:17 +01004956 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004957 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004958
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004960 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4961 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004962 err_code |= ERR_ALERT | ERR_FATAL;
4963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004964 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004965
4966 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004967 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4968 free(curproxy->conn_src.iface_name);
4969 curproxy->conn_src.iface_name = NULL;
4970 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004971
Willy Tarreaud5191e72010-02-09 20:50:45 +01004972 sk = str2sa(args[1]);
4973 if (!sk) {
4974 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
4977 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004978 curproxy->conn_src.source_addr = *sk;
4979 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004980
4981 cur_arg = 2;
4982 while (*(args[cur_arg])) {
4983 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004984#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4985#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004986 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004987 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4988 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004991 }
4992#endif
4993 if (!*args[cur_arg + 1]) {
4994 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4995 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004996 err_code |= ERR_ALERT | ERR_FATAL;
4997 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004998 }
4999
5000 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005001 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5002 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005003 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005004 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5005 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005006 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5007 char *name, *end;
5008
5009 name = args[cur_arg+1] + 7;
5010 while (isspace(*name))
5011 name++;
5012
5013 end = name;
5014 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5015 end++;
5016
Willy Tarreauef9a3602012-12-08 22:29:20 +01005017 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5018 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5019 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5020 curproxy->conn_src.bind_hdr_len = end - name;
5021 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5022 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5023 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005024
5025 /* now look for an occurrence number */
5026 while (isspace(*end))
5027 end++;
5028 if (*end == ',') {
5029 end++;
5030 name = end;
5031 if (*end == '-')
5032 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005033 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005034 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005035 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005036 }
5037
Willy Tarreauef9a3602012-12-08 22:29:20 +01005038 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005039 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5040 " occurrences values smaller than %d.\n",
5041 file, linenum, MAX_HDR_HISTORY);
5042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
5044 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005045 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005046 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005047 if (!sk) {
5048 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5049 err_code |= ERR_ALERT | ERR_FATAL;
5050 goto out;
5051 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005052 curproxy->conn_src.tproxy_addr = *sk;
5053 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005054 }
5055 global.last_checks |= LSTCHK_NETADM;
5056#if !defined(CONFIG_HAP_LINUX_TPROXY)
5057 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005058#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005059#else /* no TPROXY support */
5060 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005061 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005064#endif
5065 cur_arg += 2;
5066 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005067 }
5068
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005069 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5070#ifdef SO_BINDTODEVICE
5071 if (!*args[cur_arg + 1]) {
5072 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5073 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005076 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005077 free(curproxy->conn_src.iface_name);
5078 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5079 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005080 global.last_checks |= LSTCHK_NETADM;
5081#else
5082 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5083 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005086#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005087 cur_arg += 2;
5088 continue;
5089 }
5090 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005091 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005094 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005096 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5097 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5098 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005103 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5105 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109
5110 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005111 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005112 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005113 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115 }
5116 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005117 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005118 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005119 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 }
5123 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005124 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005125 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005126 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005127 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 }
5130 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005131 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005132 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005133 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
5137 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005139 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005140 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005144 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005146 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005147 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005149 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005150 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005151 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005153 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005154 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005156 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005157 }
5158 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005160 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005161 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005163 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005166 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5168 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172
5173 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005174 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005175 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
5179 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005180 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005181 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005182 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005183 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 }
5186 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005187 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005188 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005189 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005190 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 }
5193 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005194 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005195 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005196 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005197 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 }
5200 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005201 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005202 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005203 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005207 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005208 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005209 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005210 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005211 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005212 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005215 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005216
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 if (curproxy == &defproxy) {
5218 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005222 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005223 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 if (*(args[1]) == 0) {
5226 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005230
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005231 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005232 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5233 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5234 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
5237 }
5238 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5239 }
5240 else if (*args[2]) {
5241 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5242 file, linenum, args[0], args[2]);
5243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
5245 }
5246
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005247 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005248 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005249 wl->s = strdup(args[1]);
5250 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005251 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005252 }
5253 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005254 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005255 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5256 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005257 err_code |= ERR_ALERT | ERR_FATAL;
5258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005260
Willy Tarreauade5ec42010-01-28 19:33:49 +01005261 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005262 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005263 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005264 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 }
5267 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005268 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005269 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005270 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005271 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
5274 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005275 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005276 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005277 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005278 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280 }
5281 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005282 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5284 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 }
5288
Willy Tarreauade5ec42010-01-28 19:33:49 +01005289 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005290 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005291 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005292 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294 }
5295 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005296 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005297 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005298 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005299 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 }
5302 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005303 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005304 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005305 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005306 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 }
5309 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005310 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005311
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 if (curproxy == &defproxy) {
5313 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005314 err_code |= ERR_ALERT | ERR_FATAL;
5315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005317 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005318 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 if (*(args[1]) == 0) {
5321 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 }
5325
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005326 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005327 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5328 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5329 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005330 err_code |= ERR_ALERT | ERR_FATAL;
5331 goto out;
5332 }
5333 err_code |= warnif_cond_requires_req(cond, file, linenum);
5334 }
5335 else if (*args[2]) {
5336 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5337 file, linenum, args[0], args[2]);
5338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005342 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005343 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005344 wl->s = strdup(args[1]);
5345 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005346 }
5347 else if (!strcmp(args[0], "errorloc") ||
5348 !strcmp(args[0], "errorloc302") ||
5349 !strcmp(args[0], "errorloc303")) { /* error location */
5350 int errnum, errlen;
5351 char *err;
5352
Willy Tarreau977b8e42006-12-29 14:19:17 +01005353 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005354 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005355
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005357 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 }
5361
5362 errnum = atol(args[1]);
5363 if (!strcmp(args[0], "errorloc303")) {
5364 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5365 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5366 } else {
5367 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5368 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5369 }
5370
Willy Tarreau0f772532006-12-23 20:51:41 +01005371 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5372 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005373 chunk_destroy(&curproxy->errmsg[rc]);
5374 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005375 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005378
5379 if (rc >= HTTP_ERR_SIZE) {
5380 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5381 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 free(err);
5383 }
5384 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005385 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5386 int errnum, errlen, fd;
5387 char *err;
5388 struct stat stat;
5389
5390 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005391 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005392
5393 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005394 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005397 }
5398
5399 fd = open(args[2], O_RDONLY);
5400 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5401 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5402 file, linenum, args[2], args[1]);
5403 if (fd >= 0)
5404 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005405 err_code |= ERR_ALERT | ERR_FATAL;
5406 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005407 }
5408
Willy Tarreau27a674e2009-08-17 07:23:33 +02005409 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005410 errlen = stat.st_size;
5411 } else {
5412 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005413 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005414 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005415 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005416 }
5417
5418 err = malloc(errlen); /* malloc() must succeed during parsing */
5419 errnum = read(fd, err, errlen);
5420 if (errnum != errlen) {
5421 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5422 file, linenum, args[2], args[1]);
5423 close(fd);
5424 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005427 }
5428 close(fd);
5429
5430 errnum = atol(args[1]);
5431 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5432 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005433 chunk_destroy(&curproxy->errmsg[rc]);
5434 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005435 break;
5436 }
5437 }
5438
5439 if (rc >= HTTP_ERR_SIZE) {
5440 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5441 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005442 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005443 free(err);
5444 }
5445 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005446 else if (!strcmp(args[0], "compression")) {
5447 struct comp *comp;
5448 if (curproxy->comp == NULL) {
5449 comp = calloc(1, sizeof(struct comp));
5450 curproxy->comp = comp;
5451 } else {
5452 comp = curproxy->comp;
5453 }
5454
5455 if (!strcmp(args[1], "algo")) {
5456 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005457 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005458
William Lallemand82fe75c2012-10-23 10:25:10 +02005459 cur_arg = 2;
5460 if (!*args[cur_arg]) {
5461 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5462 file, linenum, args[0]);
5463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
5465 }
5466 while (*(args[cur_arg])) {
5467 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5468 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5469 file, linenum, args[0], args[cur_arg]);
5470 err_code |= ERR_ALERT | ERR_FATAL;
5471 goto out;
5472 }
William Lallemand552df672012-11-07 13:21:47 +01005473 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5474 curproxy->comp->algos->end(&ctx);
5475 } else {
5476 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5477 file, linenum, args[0], args[cur_arg]);
5478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
5480 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005481 cur_arg ++;
5482 continue;
5483 }
5484 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005485 else if (!strcmp(args[1], "offload")) {
5486 comp->offload = 1;
5487 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005488 else if (!strcmp(args[1], "type")) {
5489 int cur_arg;
5490 cur_arg = 2;
5491 if (!*args[cur_arg]) {
5492 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5493 file, linenum, args[0]);
5494 err_code |= ERR_ALERT | ERR_FATAL;
5495 goto out;
5496 }
5497 while (*(args[cur_arg])) {
5498 comp_append_type(comp, args[cur_arg]);
5499 cur_arg ++;
5500 continue;
5501 }
5502 }
5503 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005504 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005505 file, linenum, args[0]);
5506 err_code |= ERR_ALERT | ERR_FATAL;
5507 goto out;
5508 }
5509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005511 struct cfg_kw_list *kwl;
5512 int index;
5513
5514 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5515 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5516 if (kwl->kw[index].section != CFG_LISTEN)
5517 continue;
5518 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5519 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005520 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005521 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005522 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005523 err_code |= ERR_ALERT | ERR_FATAL;
5524 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005525 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005526 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005527 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005528 err_code |= ERR_WARN;
5529 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005530 }
Willy Tarreau93893792009-07-23 13:19:11 +02005531 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005532 }
5533 }
5534 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005535
Willy Tarreau6daf3432008-01-22 16:44:08 +01005536 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005537 err_code |= ERR_ALERT | ERR_FATAL;
5538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539 }
Willy Tarreau93893792009-07-23 13:19:11 +02005540 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005541 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005542 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543}
5544
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005545int
5546cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5547{
5548
5549 int err_code = 0;
5550 const char *err;
5551
5552 if (!strcmp(args[0], "userlist")) { /* new userlist */
5553 struct userlist *newul;
5554
5555 if (!*args[1]) {
5556 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5557 file, linenum, args[0]);
5558 err_code |= ERR_ALERT | ERR_FATAL;
5559 goto out;
5560 }
5561
5562 err = invalid_char(args[1]);
5563 if (err) {
5564 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5565 file, linenum, *err, args[0], args[1]);
5566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
5568 }
5569
5570 for (newul = userlist; newul; newul = newul->next)
5571 if (!strcmp(newul->name, args[1])) {
5572 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5573 file, linenum, args[1]);
5574 err_code |= ERR_WARN;
5575 goto out;
5576 }
5577
5578 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5579 if (!newul) {
5580 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5581 err_code |= ERR_ALERT | ERR_ABORT;
5582 goto out;
5583 }
5584
5585 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5586 newul->name = strdup(args[1]);
5587
5588 if (!newul->groupusers | !newul->name) {
5589 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5590 err_code |= ERR_ALERT | ERR_ABORT;
5591 goto out;
5592 }
5593
5594 newul->next = userlist;
5595 userlist = newul;
5596
5597 } else if (!strcmp(args[0], "group")) { /* new group */
5598 int cur_arg, i;
5599 const char *err;
5600
5601 if (!*args[1]) {
5602 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5603 file, linenum, args[0]);
5604 err_code |= ERR_ALERT | ERR_FATAL;
5605 goto out;
5606 }
5607
5608 err = invalid_char(args[1]);
5609 if (err) {
5610 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5611 file, linenum, *err, args[0], args[1]);
5612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614 }
5615
5616 for(i = 0; i < userlist->grpcnt; i++)
5617 if (!strcmp(userlist->groups[i], args[1])) {
5618 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5619 file, linenum, args[1], userlist->name);
5620 err_code |= ERR_ALERT;
5621 goto out;
5622 }
5623
5624 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5625 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5626 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
5629 }
5630
5631 cur_arg = 2;
5632
5633 while (*args[cur_arg]) {
5634 if (!strcmp(args[cur_arg], "users")) {
5635 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5636 cur_arg += 2;
5637 continue;
5638 } else {
5639 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5640 file, linenum, args[0]);
5641 err_code |= ERR_ALERT | ERR_FATAL;
5642 goto out;
5643 }
5644 }
5645
5646 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5647 } else if (!strcmp(args[0], "user")) { /* new user */
5648 struct auth_users *newuser;
5649 int cur_arg;
5650
5651 if (!*args[1]) {
5652 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5653 file, linenum, args[0]);
5654 err_code |= ERR_ALERT | ERR_FATAL;
5655 goto out;
5656 }
5657
5658 for (newuser = userlist->users; newuser; newuser = newuser->next)
5659 if (!strcmp(newuser->user, args[1])) {
5660 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5661 file, linenum, args[1], userlist->name);
5662 err_code |= ERR_ALERT;
5663 goto out;
5664 }
5665
5666 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5667 if (!newuser) {
5668 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5669 err_code |= ERR_ALERT | ERR_ABORT;
5670 goto out;
5671 }
5672
5673 newuser->user = strdup(args[1]);
5674
5675 newuser->next = userlist->users;
5676 userlist->users = newuser;
5677
5678 cur_arg = 2;
5679
5680 while (*args[cur_arg]) {
5681 if (!strcmp(args[cur_arg], "password")) {
5682#ifndef CONFIG_HAP_CRYPT
5683 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5684 file, linenum);
5685 err_code |= ERR_ALERT;
5686#endif
5687 newuser->pass = strdup(args[cur_arg + 1]);
5688 cur_arg += 2;
5689 continue;
5690 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5691 newuser->pass = strdup(args[cur_arg + 1]);
5692 newuser->flags |= AU_O_INSECURE;
5693 cur_arg += 2;
5694 continue;
5695 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005696 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005697 cur_arg += 2;
5698 continue;
5699 } else {
5700 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5701 file, linenum, args[0]);
5702 err_code |= ERR_ALERT | ERR_FATAL;
5703 goto out;
5704 }
5705 }
5706 } else {
5707 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5708 err_code |= ERR_ALERT | ERR_FATAL;
5709 }
5710
5711out:
5712 return err_code;
5713}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714
5715/*
5716 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005717 * Returns the error code, 0 if OK, or any combination of :
5718 * - ERR_ABORT: must abort ASAP
5719 * - ERR_FATAL: we can continue parsing but not start the service
5720 * - ERR_WARN: a warning has been emitted
5721 * - ERR_ALERT: an alert has been emitted
5722 * Only the two first ones can stop processing, the two others are just
5723 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005725int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005727 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 FILE *f;
5729 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005730 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005731 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005732
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733 if ((f=fopen(file,"r")) == NULL)
5734 return -1;
5735
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005736 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005737 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005738 char *end;
5739 char *args[MAX_LINE_ARGS + 1];
5740 char *line = thisline;
5741
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742 linenum++;
5743
5744 end = line + strlen(line);
5745
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005746 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5747 /* Check if we reached the limit and the last char is not \n.
5748 * Watch out for the last line without the terminating '\n'!
5749 */
5750 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005751 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005752 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005753 }
5754
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005756 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 line++;
5758
5759 arg = 0;
5760 args[arg] = line;
5761
5762 while (*line && arg < MAX_LINE_ARGS) {
5763 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5764 * C equivalent value. Other combinations left unchanged (eg: \1).
5765 */
5766 if (*line == '\\') {
5767 int skip = 0;
5768 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5769 *line = line[1];
5770 skip = 1;
5771 }
5772 else if (line[1] == 'r') {
5773 *line = '\r';
5774 skip = 1;
5775 }
5776 else if (line[1] == 'n') {
5777 *line = '\n';
5778 skip = 1;
5779 }
5780 else if (line[1] == 't') {
5781 *line = '\t';
5782 skip = 1;
5783 }
5784 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005785 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 unsigned char hex1, hex2;
5787 hex1 = toupper(line[2]) - '0';
5788 hex2 = toupper(line[3]) - '0';
5789 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5790 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5791 *line = (hex1<<4) + hex2;
5792 skip = 3;
5793 }
5794 else {
5795 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005796 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797 }
5798 }
5799 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005800 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801 end -= skip;
5802 }
5803 line++;
5804 }
5805 else if (*line == '#' || *line == '\n' || *line == '\r') {
5806 /* end of string, end of loop */
5807 *line = 0;
5808 break;
5809 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005810 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005812 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005813 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814 line++;
5815 args[++arg] = line;
5816 }
5817 else {
5818 line++;
5819 }
5820 }
5821
5822 /* empty line */
5823 if (!**args)
5824 continue;
5825
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005826 if (*line) {
5827 /* we had to stop due to too many args.
5828 * Let's terminate the string, print the offending part then cut the
5829 * last arg.
5830 */
5831 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5832 line++;
5833 *line = '\0';
5834
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005835 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005836 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005837 err_code |= ERR_ALERT | ERR_FATAL;
5838 args[arg] = line;
5839 }
5840
Willy Tarreau540abe42007-05-02 20:50:16 +02005841 /* zero out remaining args and ensure that at least one entry
5842 * is zeroed out.
5843 */
5844 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005845 args[arg] = line;
5846 }
5847
Willy Tarreau3842f002009-06-14 11:39:52 +02005848 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005849 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005850 char *tmp;
5851
Willy Tarreau3842f002009-06-14 11:39:52 +02005852 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005853 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005854 for (arg=0; *args[arg+1]; arg++)
5855 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005856 *tmp = '\0'; // fix the next arg to \0
5857 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005858 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005859 else if (!strcmp(args[0], "default")) {
5860 kwm = KWM_DEF;
5861 for (arg=0; *args[arg+1]; arg++)
5862 args[arg] = args[arg+1]; // shift args after inversion
5863 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005864
William Lallemand0f99e342011-10-12 17:50:54 +02005865 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5866 strcmp(args[0], "log") != 0) {
5867 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005868 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005869 }
5870
Willy Tarreau977b8e42006-12-29 14:19:17 +01005871 if (!strcmp(args[0], "listen") ||
5872 !strcmp(args[0], "frontend") ||
5873 !strcmp(args[0], "backend") ||
5874 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005875 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005876 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005877 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005878 cursection = strdup(args[0]);
5879 }
5880 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005881 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005882 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005883 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005884 }
5885 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005886 confsect = CFG_USERLIST;
5887 free(cursection);
5888 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005889 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005890 else if (!strcmp(args[0], "peers")) {
5891 confsect = CFG_PEERS;
5892 free(cursection);
5893 cursection = strdup(args[0]);
5894 }
5895
Willy Tarreaubaaee002006-06-26 02:48:02 +02005896 /* else it's a section keyword */
5897
5898 switch (confsect) {
5899 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005900 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 break;
5902 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005903 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005904 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005905 case CFG_USERLIST:
5906 err_code |= cfg_parse_users(file, linenum, args, kwm);
5907 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005908 case CFG_PEERS:
5909 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5910 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005911 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005912 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005913 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005915
5916 if (err_code & ERR_ABORT)
5917 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005918 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005919 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005920 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005921 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005922 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005923}
5924
Willy Tarreaubb925012009-07-23 13:36:36 +02005925/*
5926 * Returns the error code, 0 if OK, or any combination of :
5927 * - ERR_ABORT: must abort ASAP
5928 * - ERR_FATAL: we can continue parsing but not start the service
5929 * - ERR_WARN: a warning has been emitted
5930 * - ERR_ALERT: an alert has been emitted
5931 * Only the two first ones can stop processing, the two others are just
5932 * indicators.
5933 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005934int check_config_validity()
5935{
5936 int cfgerr = 0;
5937 struct proxy *curproxy = NULL;
5938 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005939 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005940 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005941 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005942 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005943
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005944 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005945 /*
5946 * Now, check for the integrity of all that we have collected.
5947 */
5948
5949 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005950 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005951
Willy Tarreau193b8c62012-11-22 00:17:38 +01005952 if (!global.tune.max_http_hdr)
5953 global.tune.max_http_hdr = MAX_HTTP_HDR;
5954
5955 if (!global.tune.cookie_len)
5956 global.tune.cookie_len = CAPTURE_LEN;
5957
5958 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5959
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005960 /* first, we will invert the proxy list order */
5961 curproxy = NULL;
5962 while (proxy) {
5963 struct proxy *next;
5964
5965 next = proxy->next;
5966 proxy->next = curproxy;
5967 curproxy = proxy;
5968 if (!next)
5969 break;
5970 proxy = next;
5971 }
5972
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005974 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005975 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005976 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005977 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005978 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005979 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005980 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005981
Willy Tarreau050536d2012-10-04 08:47:34 +02005982 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005983 /* proxy ID not set, use automatic numbering with first
5984 * spare entry starting with next_pxid.
5985 */
5986 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5987 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5988 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005989 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005990 next_pxid++;
5991
Willy Tarreau55ea7572007-06-17 19:56:27 +02005992
Willy Tarreaubaaee002006-06-26 02:48:02 +02005993 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005994 /* ensure we don't keep listeners uselessly bound */
5995 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005996 curproxy = curproxy->next;
5997 continue;
5998 }
5999
Willy Tarreau16a21472012-11-19 12:39:59 +01006000 /* number of processes this proxy is bound to */
6001 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6002
Willy Tarreauff01a212009-03-15 13:46:16 +01006003 switch (curproxy->mode) {
6004 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006005 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006006 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006007 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6008 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006009 cfgerr++;
6010 }
6011
6012 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006013 Warning("config : servers will be ignored for %s '%s'.\n",
6014 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006015 break;
6016
6017 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006018 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006019 break;
6020
6021 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006022 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006023 break;
6024 }
6025
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006026 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006027 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006028 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006029 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6030 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006031 cfgerr++;
6032 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006034 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006035 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6036 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006037 cfgerr++;
6038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006040 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006041 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6042 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006043 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006044 }
6045 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006046 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006047 /* If no LB algo is set in a backend, and we're not in
6048 * transparent mode, dispatch mode nor proxy mode, we
6049 * want to use balance roundrobin by default.
6050 */
6051 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6052 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053 }
6054 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006055
Willy Tarreau1620ec32011-08-06 17:05:02 +02006056 if (curproxy->options & PR_O_DISPATCH)
6057 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6058 else if (curproxy->options & PR_O_HTTP_PROXY)
6059 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6060 else if (curproxy->options & PR_O_TRANSP)
6061 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006062
Willy Tarreau1620ec32011-08-06 17:05:02 +02006063 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6064 if (curproxy->options & PR_O_DISABLE404) {
6065 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6066 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6067 err_code |= ERR_WARN;
6068 curproxy->options &= ~PR_O_DISABLE404;
6069 }
6070 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6071 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6072 "send-state", proxy_type_str(curproxy), curproxy->id);
6073 err_code |= ERR_WARN;
6074 curproxy->options &= ~PR_O2_CHK_SNDST;
6075 }
Willy Tarreauef781042010-01-27 11:53:01 +01006076 }
6077
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006078 /* if a default backend was specified, let's find it */
6079 if (curproxy->defbe.name) {
6080 struct proxy *target;
6081
Alex Williams96532db2009-11-01 21:27:13 -05006082 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006083 if (!target) {
6084 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6085 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006086 cfgerr++;
6087 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006088 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6089 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006090 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006091 } else {
6092 free(curproxy->defbe.name);
6093 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006094 /* we force the backend to be present on at least all of
6095 * the frontend's processes.
6096 */
6097 target->bind_proc = curproxy->bind_proc ?
6098 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006099
6100 /* Emit a warning if this proxy also has some servers */
6101 if (curproxy->srv) {
6102 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6103 curproxy->id);
6104 err_code |= ERR_WARN;
6105 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006106 }
6107 }
6108
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006109 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006110 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6111 /* map jump target for ACT_SETBE in req_rep chain */
6112 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006113 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006114 struct proxy *target;
6115
Willy Tarreaua496b602006-12-17 23:15:24 +01006116 if (exp->action != ACT_SETBE)
6117 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006118
Alex Williams96532db2009-11-01 21:27:13 -05006119 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006120 if (!target) {
6121 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6122 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006123 cfgerr++;
6124 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006125 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6126 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006127 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006128 } else {
6129 free((void *)exp->replace);
6130 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006131 /* we force the backend to be present on at least all of
6132 * the frontend's processes.
6133 */
6134 target->bind_proc = curproxy->bind_proc ?
6135 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006136 }
6137 }
6138 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006139
6140 /* find the target proxy for 'use_backend' rules */
6141 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006142 struct proxy *target;
6143
Alex Williams96532db2009-11-01 21:27:13 -05006144 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006145
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006146 if (!target) {
6147 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6148 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006149 cfgerr++;
6150 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006151 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6152 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006153 cfgerr++;
6154 } else {
6155 free((void *)rule->be.name);
6156 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006157 /* we force the backend to be present on at least all of
6158 * the frontend's processes.
6159 */
6160 target->bind_proc = curproxy->bind_proc ?
6161 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006162 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006163 }
6164
6165 /* find the target proxy for 'use_backend' rules */
6166 list_for_each_entry(srule, &curproxy->server_rules, list) {
6167 struct server *target = findserver(curproxy, srule->srv.name);
6168
6169 if (!target) {
6170 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6171 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6172 cfgerr++;
6173 continue;
6174 }
6175 free((void *)srule->srv.name);
6176 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006177 }
6178
Emeric Brunb982a3d2010-01-04 15:45:53 +01006179 /* find the target table for 'stick' rules */
6180 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6181 struct proxy *target;
6182
Emeric Brun1d33b292010-01-04 15:47:17 +01006183 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6184 if (mrule->flags & STK_IS_STORE)
6185 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6186
Emeric Brunb982a3d2010-01-04 15:45:53 +01006187 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006188 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006189 else
6190 target = curproxy;
6191
6192 if (!target) {
6193 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6194 curproxy->id, mrule->table.name);
6195 cfgerr++;
6196 }
6197 else if (target->table.size == 0) {
6198 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6199 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6200 cfgerr++;
6201 }
Willy Tarreau12785782012-04-27 21:37:17 +02006202 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6203 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006204 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6205 cfgerr++;
6206 }
6207 else {
6208 free((void *)mrule->table.name);
6209 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006210 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006211 }
6212 }
6213
6214 /* find the target table for 'store response' rules */
6215 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6216 struct proxy *target;
6217
Emeric Brun1d33b292010-01-04 15:47:17 +01006218 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6219
Emeric Brunb982a3d2010-01-04 15:45:53 +01006220 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006221 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006222 else
6223 target = curproxy;
6224
6225 if (!target) {
6226 Alert("Proxy '%s': unable to find store table '%s'.\n",
6227 curproxy->id, mrule->table.name);
6228 cfgerr++;
6229 }
6230 else if (target->table.size == 0) {
6231 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6232 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6233 cfgerr++;
6234 }
Willy Tarreau12785782012-04-27 21:37:17 +02006235 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6236 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006237 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6238 cfgerr++;
6239 }
6240 else {
6241 free((void *)mrule->table.name);
6242 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006243 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006244 }
6245 }
6246
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006247 /* find the target table for 'tcp-request' layer 4 rules */
6248 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6249 struct proxy *target;
6250
Willy Tarreau56123282010-08-06 19:06:56 +02006251 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006252 continue;
6253
6254 if (trule->act_prm.trk_ctr.table.n)
6255 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6256 else
6257 target = curproxy;
6258
6259 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006260 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6261 curproxy->id, trule->act_prm.trk_ctr.table.n,
6262 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006263 cfgerr++;
6264 }
6265 else if (target->table.size == 0) {
6266 Alert("Proxy '%s': table '%s' used but not configured.\n",
6267 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6268 cfgerr++;
6269 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006270 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6271 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6272 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6273 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6274 cfgerr++;
6275 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006276 else {
6277 free(trule->act_prm.trk_ctr.table.n);
6278 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006279 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006280 * to pass a list of counters to track and allocate them right here using
6281 * stktable_alloc_data_type().
6282 */
6283 }
6284 }
6285
Willy Tarreaud1f96522010-08-03 19:34:32 +02006286 /* find the target table for 'tcp-request' layer 6 rules */
6287 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6288 struct proxy *target;
6289
Willy Tarreau56123282010-08-06 19:06:56 +02006290 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006291 continue;
6292
6293 if (trule->act_prm.trk_ctr.table.n)
6294 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6295 else
6296 target = curproxy;
6297
6298 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006299 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6300 curproxy->id, trule->act_prm.trk_ctr.table.n,
6301 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006302 cfgerr++;
6303 }
6304 else if (target->table.size == 0) {
6305 Alert("Proxy '%s': table '%s' used but not configured.\n",
6306 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6307 cfgerr++;
6308 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006309 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6310 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6311 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6312 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6313 cfgerr++;
6314 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006315 else {
6316 free(trule->act_prm.trk_ctr.table.n);
6317 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006318 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006319 * to pass a list of counters to track and allocate them right here using
6320 * stktable_alloc_data_type().
6321 */
6322 }
6323 }
6324
Emeric Brun32da3c42010-09-23 18:39:19 +02006325 if (curproxy->table.peers.name) {
6326 struct peers *curpeers = peers;
6327
6328 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6329 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6330 free((void *)curproxy->table.peers.name);
6331 curproxy->table.peers.p = peers;
6332 break;
6333 }
6334 }
6335
6336 if (!curpeers) {
6337 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6338 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006339 free((void *)curproxy->table.peers.name);
6340 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006341 cfgerr++;
6342 }
6343 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006344 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6345 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006346 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006347 cfgerr++;
6348 }
6349 }
6350
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006351 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006352 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006353 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6354 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6355 "proxy", curproxy->id);
6356 cfgerr++;
6357 goto out_uri_auth_compat;
6358 }
6359
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006360 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006361 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006362 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006363 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006364
Willy Tarreau95fa4692010-02-01 13:05:50 +01006365 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6366 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006367
6368 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006369 uri_auth_compat_req[i++] = "realm";
6370 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6371 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006372
Willy Tarreau95fa4692010-02-01 13:05:50 +01006373 uri_auth_compat_req[i++] = "unless";
6374 uri_auth_compat_req[i++] = "{";
6375 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6376 uri_auth_compat_req[i++] = "}";
6377 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006378
Willy Tarreauff011f22011-01-06 17:51:27 +01006379 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6380 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006381 cfgerr++;
6382 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006383 }
6384
Willy Tarreauff011f22011-01-06 17:51:27 +01006385 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006386
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006387 if (curproxy->uri_auth->auth_realm) {
6388 free(curproxy->uri_auth->auth_realm);
6389 curproxy->uri_auth->auth_realm = NULL;
6390 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006391
6392 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006393 }
6394out_uri_auth_compat:
6395
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006396 cfgerr += acl_find_targets(curproxy);
6397
Willy Tarreau2738a142006-07-08 17:28:09 +02006398 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006399 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006400 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006401 (!curproxy->timeout.connect ||
6402 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006403 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006404 " | While not properly invalid, you will certainly encounter various problems\n"
6405 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006406 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006407 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006408 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006409 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006410
Willy Tarreau1fa31262007-12-03 00:36:16 +01006411 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6412 * We must still support older configurations, so let's find out whether those
6413 * parameters have been set or must be copied from contimeouts.
6414 */
6415 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006416 if (!curproxy->timeout.tarpit ||
6417 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006418 /* tarpit timeout not set. We search in the following order:
6419 * default.tarpit, curr.connect, default.connect.
6420 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006421 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006422 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006423 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006424 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006425 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006426 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006427 }
6428 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006429 (!curproxy->timeout.queue ||
6430 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006431 /* queue timeout not set. We search in the following order:
6432 * default.queue, curr.connect, default.connect.
6433 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006434 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006435 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006436 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006437 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006438 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006439 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006440 }
6441 }
6442
Willy Tarreau1620ec32011-08-06 17:05:02 +02006443 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006444 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6445 curproxy->check_req = (char *)malloc(curproxy->check_len);
6446 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006447 }
6448
Willy Tarreau193b8c62012-11-22 00:17:38 +01006449 /* ensure that cookie capture length is not too large */
6450 if (curproxy->capture_len >= global.tune.cookie_len) {
6451 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6452 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6453 err_code |= ERR_WARN;
6454 curproxy->capture_len = global.tune.cookie_len - 1;
6455 }
6456
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006457 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006458 if (curproxy->nb_req_cap) {
6459 if (curproxy->mode == PR_MODE_HTTP) {
6460 curproxy->req_cap_pool = create_pool("ptrcap",
6461 curproxy->nb_req_cap * sizeof(char *),
6462 MEM_F_SHARED);
6463 } else {
6464 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6465 proxy_type_str(curproxy), curproxy->id);
6466 err_code |= ERR_WARN;
6467 curproxy->to_log &= ~LW_REQHDR;
6468 curproxy->nb_req_cap = 0;
6469 }
6470 }
6471
6472 if (curproxy->nb_rsp_cap) {
6473 if (curproxy->mode == PR_MODE_HTTP) {
6474 curproxy->rsp_cap_pool = create_pool("ptrcap",
6475 curproxy->nb_rsp_cap * sizeof(char *),
6476 MEM_F_SHARED);
6477 } else {
6478 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6479 proxy_type_str(curproxy), curproxy->id);
6480 err_code |= ERR_WARN;
6481 curproxy->to_log &= ~LW_REQHDR;
6482 curproxy->nb_rsp_cap = 0;
6483 }
6484 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006485
Willy Tarreau196729e2012-05-31 19:30:26 +02006486 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006487 if (!(curproxy->cap & PR_CAP_FE)) {
6488 if (curproxy->logformat_string != default_http_log_format &&
6489 curproxy->logformat_string != default_tcp_log_format &&
6490 curproxy->logformat_string != clf_http_log_format)
6491 free(curproxy->logformat_string);
6492 curproxy->logformat_string = NULL;
6493 }
6494
Willy Tarreau196729e2012-05-31 19:30:26 +02006495 if (curproxy->logformat_string)
6496 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6497
6498 if (curproxy->uniqueid_format_string)
6499 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6500
Willy Tarreaubaaee002006-06-26 02:48:02 +02006501 /* first, we will invert the servers list order */
6502 newsrv = NULL;
6503 while (curproxy->srv) {
6504 struct server *next;
6505
6506 next = curproxy->srv->next;
6507 curproxy->srv->next = newsrv;
6508 newsrv = curproxy->srv;
6509 if (!next)
6510 break;
6511 curproxy->srv = next;
6512 }
6513
Willy Tarreaudd701652010-05-25 23:03:02 +02006514 /* assign automatic UIDs to servers which don't have one yet */
6515 next_id = 1;
6516 newsrv = curproxy->srv;
6517 while (newsrv != NULL) {
6518 if (!newsrv->puid) {
6519 /* server ID not set, use automatic numbering with first
6520 * spare entry starting with next_svid.
6521 */
6522 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6523 newsrv->conf.id.key = newsrv->puid = next_id;
6524 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6525 }
6526 next_id++;
6527 newsrv = newsrv->next;
6528 }
6529
Willy Tarreau20697042007-11-15 23:26:18 +01006530 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006531 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006532
Willy Tarreau62c3be22012-01-20 13:12:32 +01006533 /*
6534 * If this server supports a maxconn parameter, it needs a dedicated
6535 * tasks to fill the emptied slots when a connection leaves.
6536 * Also, resolve deferred tracking dependency if needed.
6537 */
6538 newsrv = curproxy->srv;
6539 while (newsrv != NULL) {
6540 if (newsrv->minconn > newsrv->maxconn) {
6541 /* Only 'minconn' was specified, or it was higher than or equal
6542 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6543 * this will avoid further useless expensive computations.
6544 */
6545 newsrv->maxconn = newsrv->minconn;
6546 } else if (newsrv->maxconn && !newsrv->minconn) {
6547 /* minconn was not specified, so we set it to maxconn */
6548 newsrv->minconn = newsrv->maxconn;
6549 }
6550
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006551#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006552 if (newsrv->use_ssl || newsrv->check.use_ssl)
6553 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006554#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006555
Willy Tarreau62c3be22012-01-20 13:12:32 +01006556 if (newsrv->trackit) {
6557 struct proxy *px;
6558 struct server *srv;
6559 char *pname, *sname;
6560
6561 pname = newsrv->trackit;
6562 sname = strrchr(pname, '/');
6563
6564 if (sname)
6565 *sname++ = '\0';
6566 else {
6567 sname = pname;
6568 pname = NULL;
6569 }
6570
6571 if (pname) {
6572 px = findproxy(pname, PR_CAP_BE);
6573 if (!px) {
6574 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6575 proxy_type_str(curproxy), curproxy->id,
6576 newsrv->id, pname);
6577 cfgerr++;
6578 goto next_srv;
6579 }
6580 } else
6581 px = curproxy;
6582
6583 srv = findserver(px, sname);
6584 if (!srv) {
6585 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6586 proxy_type_str(curproxy), curproxy->id,
6587 newsrv->id, sname);
6588 cfgerr++;
6589 goto next_srv;
6590 }
6591
6592 if (!(srv->state & SRV_CHECKED)) {
6593 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6594 "tracking as it does not have checks enabled.\n",
6595 proxy_type_str(curproxy), curproxy->id,
6596 newsrv->id, px->id, srv->id);
6597 cfgerr++;
6598 goto next_srv;
6599 }
6600
6601 if (curproxy != px &&
6602 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6603 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6604 "tracking: disable-on-404 option inconsistency.\n",
6605 proxy_type_str(curproxy), curproxy->id,
6606 newsrv->id, px->id, srv->id);
6607 cfgerr++;
6608 goto next_srv;
6609 }
6610
6611 /* if the other server is forced disabled, we have to do the same here */
6612 if (srv->state & SRV_MAINTAIN) {
6613 newsrv->state |= SRV_MAINTAIN;
6614 newsrv->state &= ~SRV_RUNNING;
6615 newsrv->health = 0;
6616 }
6617
6618 newsrv->track = srv;
6619 newsrv->tracknext = srv->tracknext;
6620 srv->tracknext = newsrv;
6621
6622 free(newsrv->trackit);
6623 newsrv->trackit = NULL;
6624 }
6625 next_srv:
6626 newsrv = newsrv->next;
6627 }
6628
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006629 /* We have to initialize the server lookup mechanism depending
6630 * on what LB algorithm was choosen.
6631 */
6632
6633 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6634 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6635 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006636 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6637 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6638 init_server_map(curproxy);
6639 } else {
6640 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6641 fwrr_init_server_groups(curproxy);
6642 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006643 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006644
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006645 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006646 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6647 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6648 fwlc_init_server_tree(curproxy);
6649 } else {
6650 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6651 fas_init_server_tree(curproxy);
6652 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006653 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006654
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006655 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006656 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6657 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6658 chash_init_server_tree(curproxy);
6659 } else {
6660 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6661 init_server_map(curproxy);
6662 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006663 break;
6664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006665
6666 if (curproxy->options & PR_O_LOGASAP)
6667 curproxy->to_log &= ~LW_BYTES;
6668
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006669 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006670 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006671 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6672 proxy_type_str(curproxy), curproxy->id);
6673 err_code |= ERR_WARN;
6674 }
6675
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006676 if (curproxy->mode != PR_MODE_HTTP) {
6677 int optnum;
6678
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006679 if (curproxy->uri_auth) {
6680 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6681 proxy_type_str(curproxy), curproxy->id);
6682 err_code |= ERR_WARN;
6683 curproxy->uri_auth = NULL;
6684 }
6685
Willy Tarreau87cf5142011-08-19 22:57:24 +02006686 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006687 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6688 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6689 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006690 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006691 }
6692
6693 if (curproxy->options & PR_O_ORGTO) {
6694 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6695 "originalto", proxy_type_str(curproxy), curproxy->id);
6696 err_code |= ERR_WARN;
6697 curproxy->options &= ~PR_O_ORGTO;
6698 }
6699
6700 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6701 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6702 (curproxy->cap & cfg_opts[optnum].cap) &&
6703 (curproxy->options & cfg_opts[optnum].val)) {
6704 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6705 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6706 err_code |= ERR_WARN;
6707 curproxy->options &= ~cfg_opts[optnum].val;
6708 }
6709 }
6710
6711 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6712 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6713 (curproxy->cap & cfg_opts2[optnum].cap) &&
6714 (curproxy->options2 & cfg_opts2[optnum].val)) {
6715 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6716 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6717 err_code |= ERR_WARN;
6718 curproxy->options2 &= ~cfg_opts2[optnum].val;
6719 }
6720 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006721
Willy Tarreauefa5f512010-03-30 20:13:29 +02006722#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006723 if (curproxy->conn_src.bind_hdr_occ) {
6724 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006725 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006726 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006727 err_code |= ERR_WARN;
6728 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006729#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006730 }
6731
Willy Tarreaubaaee002006-06-26 02:48:02 +02006732 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006733 * ensure that we're not cross-dressing a TCP server into HTTP.
6734 */
6735 newsrv = curproxy->srv;
6736 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006737 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006738 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6739 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006740 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006741 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006742
Willy Tarreau0cec3312011-10-31 13:49:26 +01006743 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6744 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6745 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6746 err_code |= ERR_WARN;
6747 }
6748
Willy Tarreauefa5f512010-03-30 20:13:29 +02006749#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006750 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6751 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006752 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 +01006753 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006754 err_code |= ERR_WARN;
6755 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006756#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006757 newsrv = newsrv->next;
6758 }
6759
Willy Tarreauc1a21672009-08-16 22:37:44 +02006760 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006761 if (!curproxy->accept)
6762 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006763
Willy Tarreauc1a21672009-08-16 22:37:44 +02006764 if (curproxy->tcp_req.inspect_delay ||
6765 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006766 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006767
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006768 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006769 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006770 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006771 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006772
6773 /* both TCP and HTTP must check switching rules */
6774 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6775 }
6776
6777 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006778 if (curproxy->tcp_req.inspect_delay ||
6779 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6780 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6781
Emeric Brun97679e72010-09-23 17:56:44 +02006782 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6783 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6784
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006785 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006786 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006787 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006788 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006789
6790 /* If the backend does requires RDP cookie persistence, we have to
6791 * enable the corresponding analyser.
6792 */
6793 if (curproxy->options2 & PR_O2_RDPC_PRST)
6794 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6795 }
6796
Emeric Brunc52962f2012-11-15 18:28:02 +01006797#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006798 /* Configure SSL for each bind line.
6799 * Note: if configuration fails at some point, the ->ctx member
6800 * remains NULL so that listeners can later detach.
6801 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006802 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006803 if (!bind_conf->is_ssl) {
6804 if (bind_conf->default_ctx) {
6805 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6806 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6807 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006808 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006809 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006810 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006811 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006812 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006813 cfgerr++;
6814 continue;
6815 }
6816
Emeric Brun4b3091e2012-09-24 15:48:52 +02006817 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006818 Alert("Unable to allocate SSL session cache.\n");
6819 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006820 continue;
6821 }
6822
Emeric Brunfc0421f2012-09-07 17:30:07 +02006823 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006824 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006825 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006826#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006827
Willy Tarreaue6b98942007-10-29 01:09:36 +01006828 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006829 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006830 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006831 if (!listener->luid) {
6832 /* listener ID not set, use automatic numbering with first
6833 * spare entry starting with next_luid.
6834 */
6835 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6836 listener->conf.id.key = listener->luid = next_id;
6837 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006838 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006839 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006840
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006841 /* enable separate counters */
6842 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6843 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006844 if (!listener->name)
6845 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006846 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006847
Willy Tarreaue6b98942007-10-29 01:09:36 +01006848 if (curproxy->options & PR_O_TCP_NOLING)
6849 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006850 if (!listener->maxconn)
6851 listener->maxconn = curproxy->maxconn;
6852 if (!listener->backlog)
6853 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006854 if (!listener->maxaccept)
6855 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6856
6857 /* we want to have an optimal behaviour on single process mode to
6858 * maximize the work at once, but in multi-process we want to keep
6859 * some fairness between processes, so we target half of the max
6860 * number of events to be balanced over all the processes the proxy
6861 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6862 * used to disable the limit.
6863 */
6864 if (listener->maxaccept > 0) {
6865 if (nbproc > 1)
6866 listener->maxaccept = (listener->maxaccept + 1) / 2;
6867 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6868 }
6869
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006870 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006871 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006872 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006873 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006874
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006875 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6876 listener->options |= LI_O_TCP_RULES;
6877
Willy Tarreaude3041d2010-05-31 10:56:17 +02006878 if (curproxy->mon_mask.s_addr)
6879 listener->options |= LI_O_CHK_MONNET;
6880
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006881 /* smart accept mode is automatic in HTTP mode */
6882 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006883 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006884 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6885 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006886 }
6887
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006888 /* Release unused SSL configs */
6889 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6890 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006891 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006892#ifdef USE_OPENSSL
6893 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006894 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006895 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006896 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006897 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006898#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006899 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006900
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006901 /* Check multi-process mode compatibility for the current proxy */
6902 if (global.nbproc > 1) {
6903 int nbproc = 0;
6904 if (curproxy->bind_proc) {
6905 int proc;
6906 for (proc = 0; proc < global.nbproc; proc++) {
6907 if (curproxy->bind_proc & (1 << proc)) {
6908 nbproc++;
6909 }
6910 }
6911 } else {
6912 nbproc = global.nbproc;
6913 }
6914 if (curproxy->table.peers.name) {
6915 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6916 curproxy->id);
6917 cfgerr++;
6918 }
6919 if (nbproc > 1) {
6920 if (curproxy->uri_auth) {
6921 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6922 curproxy->id);
6923 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6924 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6925 curproxy->id);
6926 }
6927 }
6928 if (curproxy->appsession_name) {
6929 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6930 curproxy->id);
6931 }
6932 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6933 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6934 curproxy->id);
6935 }
6936 }
6937 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006938
6939 /* create the task associated with the proxy */
6940 curproxy->task = task_new();
6941 if (curproxy->task) {
6942 curproxy->task->context = curproxy;
6943 curproxy->task->process = manage_proxy;
6944 /* no need to queue, it will be done automatically if some
6945 * listener gets limited.
6946 */
6947 curproxy->task->expire = TICK_ETERNITY;
6948 } else {
6949 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6950 curproxy->id);
6951 cfgerr++;
6952 }
6953
Willy Tarreaubaaee002006-06-26 02:48:02 +02006954 curproxy = curproxy->next;
6955 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006956
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006957 /* Check multi-process mode compatibility */
6958 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006959 if (global.stats_fe && !global.stats_fe->bind_proc) {
6960 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 +01006961 }
6962 }
6963
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006964 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6965 struct auth_users *curuser;
6966 int g;
6967
6968 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6969 unsigned int group_mask = 0;
6970 char *group = NULL;
6971
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006972 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006973 continue;
6974
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006975 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006976
6977 for (g = 0; g < curuserlist->grpcnt; g++)
6978 if (!strcmp(curuserlist->groups[g], group))
6979 break;
6980
6981 if (g == curuserlist->grpcnt) {
6982 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6983 curuserlist->name, group, curuser->user);
6984 err_code |= ERR_ALERT | ERR_FATAL;
6985 goto out;
6986 }
6987
6988 group_mask |= (1 << g);
6989 }
6990
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006991 free(curuser->u.groups);
6992 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006993 }
6994
6995 for (g = 0; g < curuserlist->grpcnt; g++) {
6996 char *user = NULL;
6997
6998 if (!curuserlist->groupusers[g])
6999 continue;
7000
7001 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7002 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7003 if (!strcmp(curuser->user, user))
7004 break;
7005
7006 if (!curuser) {
7007 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7008 curuserlist->name, user, curuserlist->groups[g]);
7009 err_code |= ERR_ALERT | ERR_FATAL;
7010 goto out;
7011 }
7012
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007013 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007014 }
7015
7016 free(curuserlist->groupusers[g]);
7017 }
7018
7019 free(curuserlist->groupusers);
7020
7021#ifdef DEBUG_AUTH
7022 for (g = 0; g < curuserlist->grpcnt; g++) {
7023 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7024
7025 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007026 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007027 fprintf(stderr, " %s", curuser->user);
7028 }
7029
7030 fprintf(stderr, "\n");
7031 }
7032#endif
7033
Willy Tarreaufbb78422011-06-05 15:38:35 +02007034 }
7035
7036 /* automatically compute fullconn if not set. We must not do it in the
7037 * loop above because cross-references are not yet fully resolved.
7038 */
7039 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7040 /* If <fullconn> is not set, let's set it to 10% of the sum of
7041 * the possible incoming frontend's maxconns.
7042 */
7043 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7044 struct proxy *fe;
7045 int total = 0;
7046
7047 /* sum up the number of maxconns of frontends which
7048 * reference this backend at least once or which are
7049 * the same one ('listen').
7050 */
7051 for (fe = proxy; fe; fe = fe->next) {
7052 struct switching_rule *rule;
7053 struct hdr_exp *exp;
7054 int found = 0;
7055
7056 if (!(fe->cap & PR_CAP_FE))
7057 continue;
7058
7059 if (fe == curproxy) /* we're on a "listen" instance */
7060 found = 1;
7061
7062 if (fe->defbe.be == curproxy) /* "default_backend" */
7063 found = 1;
7064
7065 /* check if a "use_backend" rule matches */
7066 if (!found) {
7067 list_for_each_entry(rule, &fe->switching_rules, list) {
7068 if (rule->be.backend == curproxy) {
7069 found = 1;
7070 break;
7071 }
7072 }
7073 }
7074
7075 /* check if a "reqsetbe" rule matches */
7076 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7077 if (exp->action == ACT_SETBE &&
7078 (struct proxy *)exp->replace == curproxy) {
7079 found = 1;
7080 break;
7081 }
7082 }
7083
7084 /* now we've checked all possible ways to reference a backend
7085 * from a frontend.
7086 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007087 if (!found)
7088 continue;
7089 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007090 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007091 /* we have the sum of the maxconns in <total>. We only
7092 * keep 10% of that sum to set the default fullconn, with
7093 * a hard minimum of 1 (to avoid a divide by zero).
7094 */
7095 curproxy->fullconn = (total + 9) / 10;
7096 if (!curproxy->fullconn)
7097 curproxy->fullconn = 1;
7098 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007099 }
7100
Willy Tarreau056f5682010-06-06 15:51:11 +02007101 /* initialize stick-tables on backend capable proxies. This must not
7102 * be done earlier because the data size may be discovered while parsing
7103 * other proxies.
7104 */
7105 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007106 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007107
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007108 /*
7109 * Recount currently required checks.
7110 */
7111
7112 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7113 int optnum;
7114
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007115 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7116 if (curproxy->options & cfg_opts[optnum].val)
7117 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007118
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007119 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7120 if (curproxy->options2 & cfg_opts2[optnum].val)
7121 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007122 }
7123
Willy Tarreau122541c2011-09-07 21:24:49 +02007124 if (peers) {
7125 struct peers *curpeers = peers, **last;
7126 struct peer *p, *pb;
7127
7128 /* Remove all peers sections which don't have a valid listener.
7129 * This can happen when a peers section is never referenced and
7130 * does not contain a local peer.
7131 */
7132 last = &peers;
7133 while (*last) {
7134 curpeers = *last;
7135 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007136 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007137 last = &curpeers->next;
7138 continue;
7139 }
7140
7141 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7142 curpeers->id, localpeer);
7143
7144 p = curpeers->remote;
7145 while (p) {
7146 pb = p->next;
7147 free(p->id);
7148 free(p);
7149 p = pb;
7150 }
7151
7152 /* Destroy and unlink this curpeers section.
7153 * Note: curpeers is backed up into *last.
7154 */
7155 free(curpeers->id);
7156 curpeers = curpeers->next;
7157 free(*last);
7158 *last = curpeers;
7159 }
7160 }
7161
Willy Tarreau34eb6712011-10-24 18:15:04 +02007162 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007163 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007164 MEM_F_SHARED);
7165
Willy Tarreaubb925012009-07-23 13:36:36 +02007166 if (cfgerr > 0)
7167 err_code |= ERR_ALERT | ERR_FATAL;
7168 out:
7169 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007170}
7171
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007172/*
7173 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7174 * parsing sessions.
7175 */
7176void cfg_register_keywords(struct cfg_kw_list *kwl)
7177{
7178 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7179}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007180
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007181/*
7182 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7183 */
7184void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7185{
7186 LIST_DEL(&kwl->list);
7187 LIST_INIT(&kwl->list);
7188}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007189
7190/*
7191 * Local variables:
7192 * c-indent-level: 8
7193 * c-basic-offset: 8
7194 * End:
7195 */