blob: 49a91c046ee70b97394b2fbe81516019b5c629a1 [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) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100209 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100210 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
212 str = next;
213 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100214 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 *next++ = 0;
216 }
217
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100218 ss2 = str2sa_range(str, &port, &end, err,
219 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
220 if (!ss2)
221 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100223 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100224 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100229 if (!port || !end) {
230 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
231 goto fail;
232 }
233
Emeric Bruned760922010-10-22 17:59:25 +0200234 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200235 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200236 goto fail;
237 }
238
239 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200240 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 else if (ss2->ss_family == AF_UNSPEC) {
245 socklen_t addr_len;
246
247 /* We want to attach to an already bound fd whose number
248 * is in the addr part of ss2 when cast to sockaddr_in.
249 * Note that by definition there is a single listener.
250 * We still have to determine the address family to
251 * register the correct protocol.
252 */
253 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
254 addr_len = sizeof(*ss2);
255 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
256 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
257 goto fail;
258 }
259
260 port = end = get_host_port(ss2);
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100263 /* OK the address looks correct */
264 ss = *ss2;
265
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100268 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200269 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
270 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
271 l->frontend = curproxy;
272 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273
Willy Tarreau40aa0702013-03-10 23:51:38 +0100274 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200276 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100277 l->state = LI_INIT;
278
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100279 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100281 tcpv4_add_listener(l);
282 }
Emeric Bruned760922010-10-22 17:59:25 +0200283 else if (ss.ss_family == AF_INET6) {
284 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
285 tcpv6_add_listener(l);
286 }
287 else {
Emeric Bruned760922010-10-22 17:59:25 +0200288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100417/* Report it if a request ACL condition uses some keywords that are incompatible
418 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
419 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
420 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100421 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100422static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200425 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100428 return 0;
429
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100430 acl = acl_cond_conflicts(cond, where);
431 if (acl) {
432 if (acl->name && *acl->name)
433 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
434 file, line, acl->name, sample_ckp_names(where));
435 else
436 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200437 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100438 return ERR_WARN;
439 }
440 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100441 return 0;
442
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 if (acl->name && *acl->name)
444 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446 else
447 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200448 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100449 return ERR_WARN;
450}
451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200471 else if (!strcmp(args[0], "ca-base")) {
472#ifdef USE_OPENSSL
473 if (global.ca_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.ca_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
490 else if (!strcmp(args[0], "crt-base")) {
491#ifdef USE_OPENSSL
492 if (global.crt_base != NULL) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.crt_base = strdup(args[1]);
503#else
504 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507#endif
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "daemon")) {
510 global.mode |= MODE_DAEMON;
511 }
512 else if (!strcmp(args[0], "debug")) {
513 global.mode |= MODE_DEBUG;
514 }
515 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200518 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100524 else if (!strcmp(args[0], "nosplice")) {
525 global.tune.options &= ~GTUNE_USE_SPLICE;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "quiet")) {
528 global.mode |= MODE_QUIET;
529 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200530 else if (!strcmp(args[0], "tune.maxpollevents")) {
531 if (global.tune.maxpollevents != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200540 }
541 global.tune.maxpollevents = atol(args[1]);
542 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100543 else if (!strcmp(args[0], "tune.maxaccept")) {
544 if (global.tune.maxaccept != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100553 }
554 global.tune.maxaccept = atol(args[1]);
555 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200556 else if (!strcmp(args[0], "tune.chksize")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.chksize = atol(args[1]);
563 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200564#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100565 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.sslcachesize = atol(args[1]);
572 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100573 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
574 unsigned int ssllifetime;
575 const char *res;
576
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582
583 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
584 if (res) {
585 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
586 file, linenum, *res, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590
591 global.tune.ssllifetime = ssllifetime;
592 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100593 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.ssl_max_record = atol(args[1]);
600 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200602 else if (!strcmp(args[0], "tune.bufsize")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.bufsize = atol(args[1]);
609 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
610 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100611 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200612 }
613 else if (!strcmp(args[0], "tune.maxrewrite")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.maxrewrite = atol(args[1]);
620 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
621 global.tune.maxrewrite = global.tune.bufsize / 2;
622 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100623 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
624 if (global.tune.client_rcvbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_rcvbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
637 if (global.tune.server_rcvbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_rcvbuf = atol(args[1]);
648 }
649 else if (!strcmp(args[0], "tune.sndbuf.client")) {
650 if (global.tune.client_sndbuf != 0) {
651 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT;
653 goto out;
654 }
655 if (*(args[1]) == 0) {
656 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT | ERR_FATAL;
658 goto out;
659 }
660 global.tune.client_sndbuf = atol(args[1]);
661 }
662 else if (!strcmp(args[0], "tune.sndbuf.server")) {
663 if (global.tune.server_sndbuf != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT;
666 goto out;
667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673 global.tune.server_sndbuf = atol(args[1]);
674 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200675 else if (!strcmp(args[0], "tune.pipesize")) {
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.tune.pipesize = atol(args[1]);
682 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100683 else if (!strcmp(args[0], "tune.http.cookielen")) {
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689 global.tune.cookie_len = atol(args[1]) + 1;
690 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200691 else if (!strcmp(args[0], "tune.http.maxhdr")) {
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 global.tune.max_http_hdr = atol(args[1]);
698 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100699 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
700#ifdef USE_ZLIB
701 if (*args[1]) {
702 global.tune.zlibmemlevel = atoi(args[1]);
703 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
704 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
705 file, linenum, args[0]);
706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
708 }
709 } else {
710 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715#else
716 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719#endif
720 }
721 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
722#ifdef USE_ZLIB
723 if (*args[1]) {
724 global.tune.zlibwindowsize = atoi(args[1]);
725 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
726 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
727 file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 } else {
732 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
733 file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737#else
738 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741#endif
742 }
William Lallemandf3747832012-11-09 12:33:10 +0100743 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
744 if (*args[1]) {
745 global.tune.comp_maxlevel = atoi(args[1]);
746 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
747 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
748 file, linenum, args[0]);
749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
751 }
752 } else {
753 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
754 file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 else if (!strcmp(args[0], "uid")) {
760 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200761 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200762 err_code |= ERR_ALERT;
763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770 global.uid = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "gid")) {
773 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200774 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT;
776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
783 global.gid = atol(args[1]);
784 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 /* user/group name handling */
786 else if (!strcmp(args[0], "user")) {
787 struct passwd *ha_user;
788 if (global.uid != 0) {
789 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200792 }
793 errno = 0;
794 ha_user = getpwnam(args[1]);
795 if (ha_user != NULL) {
796 global.uid = (int)ha_user->pw_uid;
797 }
798 else {
799 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 +0200800 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200801 }
802 }
803 else if (!strcmp(args[0], "group")) {
804 struct group *ha_group;
805 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200806 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT;
808 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200809 }
810 errno = 0;
811 ha_group = getgrnam(args[1]);
812 if (ha_group != NULL) {
813 global.gid = (int)ha_group->gr_gid;
814 }
815 else {
816 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 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200818 }
819 }
820 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 global.nbproc = atol(args[1]);
828 }
829 else if (!strcmp(args[0], "maxconn")) {
830 if (global.maxconn != 0) {
831 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT;
833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840 global.maxconn = atol(args[1]);
841#ifdef SYSTEM_MAXCONN
842 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
843 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);
844 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847#endif /* SYSTEM_MAXCONN */
848 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200849 else if (!strcmp(args[0], "maxsslconn")) {
850#ifdef USE_OPENSSL
851 if (*(args[1]) == 0) {
852 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
853 err_code |= ERR_ALERT | ERR_FATAL;
854 goto out;
855 }
856 global.maxsslconn = atol(args[1]);
857#else
Emeric Brun0914df82012-10-02 18:45:42 +0200858 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200861#endif
862 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200863 else if (!strcmp(args[0], "maxconnrate")) {
864 if (global.cps_lim != 0) {
865 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT;
867 goto out;
868 }
869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.cps_lim = atol(args[1]);
875 }
William Lallemandd85f9172012-11-09 17:05:39 +0100876 else if (!strcmp(args[0], "maxcomprate")) {
877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 global.comp_rate_lim = atoi(args[1]) * 1024;
883 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100884 else if (!strcmp(args[0], "maxpipes")) {
885 if (global.maxpipes != 0) {
886 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_ALERT;
888 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100889 }
890 if (*(args[1]) == 0) {
891 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100894 }
895 global.maxpipes = atol(args[1]);
896 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 else if (!strcmp(args[0], "maxzlibmem")) {
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
William Lallemande3a7d992012-11-20 11:25:20 +0100903 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100904 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100905 else if (!strcmp(args[0], "maxcompcpuusage")) {
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100912 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100913 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917}
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 else if (!strcmp(args[0], "ulimit-n")) {
920 if (global.rlimit_nofile != 0) {
921 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
925 if (*(args[1]) == 0) {
926 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930 global.rlimit_nofile = atol(args[1]);
931 }
932 else if (!strcmp(args[0], "chroot")) {
933 if (global.chroot != NULL) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 global.chroot = strdup(args[1]);
944 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200945 else if (!strcmp(args[0], "description")) {
946 int i, len=0;
947 char *d;
948
949 if (!*args[1]) {
950 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
951 file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 for(i=1; *args[i]; i++)
957 len += strlen(args[i])+1;
958
959 if (global.desc)
960 free(global.desc);
961
962 global.desc = d = (char *)calloc(1, len);
963
964 d += sprintf(d, "%s", args[1]);
965 for(i=2; *args[i]; i++)
966 d += sprintf(d, " %s", args[i]);
967 }
968 else if (!strcmp(args[0], "node")) {
969 int i;
970 char c;
971
972 for (i=0; args[1][i]; i++) {
973 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100974 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
975 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200976 break;
977 }
978
979 if (!i || args[1][i]) {
980 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
981 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
982 file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
986
987 if (global.node)
988 free(global.node);
989
990 global.node = strdup(args[1]);
991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "pidfile")) {
993 if (global.pidfile != NULL) {
994 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 }
1003 global.pidfile = strdup(args[1]);
1004 }
Emeric Bruned760922010-10-22 17:59:25 +02001005 else if (!strcmp(args[0], "unix-bind")) {
1006 int cur_arg = 1;
1007 while (*(args[cur_arg])) {
1008 if (!strcmp(args[cur_arg], "prefix")) {
1009 if (global.unix_bind.prefix != NULL) {
1010 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT;
1012 cur_arg += 2;
1013 continue;
1014 }
1015
1016 if (*(args[cur_arg+1]) == 0) {
1017 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020 }
1021 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "mode")) {
1027
1028 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "uid")) {
1034
1035 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "gid")) {
1041
1042 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1043 cur_arg += 2;
1044 continue;
1045 }
1046
1047 if (!strcmp(args[cur_arg], "user")) {
1048 struct passwd *user;
1049
1050 user = getpwnam(args[cur_arg + 1]);
1051 if (!user) {
1052 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1053 file, linenum, args[0], args[cur_arg + 1 ]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057
1058 global.unix_bind.ux.uid = user->pw_uid;
1059 cur_arg += 2;
1060 continue;
1061 }
1062
1063 if (!strcmp(args[cur_arg], "group")) {
1064 struct group *group;
1065
1066 group = getgrnam(args[cur_arg + 1]);
1067 if (!group) {
1068 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1069 file, linenum, args[0], args[cur_arg + 1 ]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073
1074 global.unix_bind.ux.gid = group->gr_gid;
1075 cur_arg += 2;
1076 continue;
1077 }
1078
Willy Tarreaub48f9582011-09-05 01:17:06 +02001079 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001080 file, linenum, args[0]);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084 }
William Lallemand0f99e342011-10-12 17:50:54 +02001085 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1086 /* delete previous herited or defined syslog servers */
1087 struct logsrv *back;
1088 struct logsrv *tmp;
1089
1090 if (*(args[1]) != 0) {
1091 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095
1096 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1097 LIST_DEL(&tmp->list);
1098 free(tmp);
1099 }
1100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001102 struct sockaddr_storage *sk;
1103 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001104 struct logsrv *logsrv;
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 if (*(args[1]) == 0 || *(args[2]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
William Lallemand0f99e342011-10-12 17:50:54 +02001111
1112 logsrv = calloc(1, sizeof(struct logsrv));
1113
1114 logsrv->facility = get_log_facility(args[2]);
1115 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120
William Lallemand0f99e342011-10-12 17:50:54 +02001121 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001123 logsrv->level = get_log_level(args[3]);
1124 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001127 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 }
1130
William Lallemand0f99e342011-10-12 17:50:54 +02001131 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001132 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001133 logsrv->minlvl = get_log_level(args[4]);
1134 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001135 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001137 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001138 }
1139 }
1140
Willy Tarreau902636f2013-03-10 19:44:48 +01001141 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001142 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001143 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001144 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001145 free(logsrv);
1146 goto out;
1147 }
1148 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001149
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001150 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001151 if (port1 != port2) {
1152 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1153 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001154 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001155 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001156 goto out;
1157 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001158
William Lallemand0f99e342011-10-12 17:50:54 +02001159 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001160 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001161 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163
William Lallemand0f99e342011-10-12 17:50:54 +02001164 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001165 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001166 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1167 char *name;
1168 int len;
1169
1170 if (global.log_send_hostname != NULL) {
1171 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT;
1173 goto out;
1174 }
1175
1176 if (*(args[1]))
1177 name = args[1];
1178 else
1179 name = hostname;
1180
1181 len = strlen(name);
1182
1183 /* We'll add a space after the name to respect the log format */
1184 free(global.log_send_hostname);
1185 global.log_send_hostname = malloc(len + 2);
1186 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1187 }
Kevinm48936af2010-12-22 16:08:21 +00001188 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
1193 }
1194 free(global.log_tag);
1195 global.log_tag = strdup(args[1]);
1196 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001197 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1198 if (global.spread_checks != 0) {
1199 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001207 }
1208 global.spread_checks = atol(args[1]);
1209 if (global.spread_checks < 0 || global.spread_checks > 50) {
1210 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001211 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001214 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1215#ifdef USE_CPU_AFFINITY
1216 int cur_arg, i;
1217 unsigned int proc = 0;
1218 unsigned long cpus = 0;
1219
1220 if (strcmp(args[1], "all") == 0)
1221 proc = 0xFFFFFFFF;
1222 else if (strcmp(args[1], "odd") == 0)
1223 proc = 0x55555555;
1224 else if (strcmp(args[1], "even") == 0)
1225 proc = 0xAAAAAAAA;
1226 else {
1227 proc = atoi(args[1]);
1228 if (proc >= 1 && proc <= 32)
1229 proc = 1 << (proc - 1);
1230 }
1231
1232 if (!proc || !*args[2]) {
1233 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",
1234 file, linenum, args[0]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 cur_arg = 2;
1240 while (*args[cur_arg]) {
1241 unsigned int low, high;
1242
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001243 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001244 char *dash = strchr(args[cur_arg], '-');
1245
1246 low = high = str2uic(args[cur_arg]);
1247 if (dash)
1248 high = str2uic(dash + 1);
1249
1250 if (high < low) {
1251 unsigned int swap = low;
1252 low = high;
1253 high = swap;
1254 }
1255
1256 if (low < 0 || high >= sizeof(long) * 8) {
1257 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1258 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 while (low <= high)
1264 cpus |= 1UL << low++;
1265 }
1266 else {
1267 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1268 file, linenum, args[0], args[cur_arg]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 cur_arg++;
1273 }
1274 for (i = 0; i < 32; i++)
1275 if (proc & (1 << i))
1276 global.cpu_map[i] = cpus;
1277#else
1278 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281#endif
1282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001284 struct cfg_kw_list *kwl;
1285 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001286 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001287
1288 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1289 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1290 if (kwl->kw[index].section != CFG_GLOBAL)
1291 continue;
1292 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001293 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001294 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001295 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001297 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001298 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001299 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_WARN;
1301 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001302 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001304 }
1305 }
1306 }
1307
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001311
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001313 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315}
1316
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001317void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001319 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 defproxy.mode = PR_MODE_TCP;
1321 defproxy.state = PR_STNEW;
1322 defproxy.maxconn = cfg_maxpconn;
1323 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001324
1325 defproxy.defsrv.inter = DEF_CHKINTR;
1326 defproxy.defsrv.fastinter = 0;
1327 defproxy.defsrv.downinter = 0;
1328 defproxy.defsrv.rise = DEF_RISETIME;
1329 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001330 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001331 defproxy.defsrv.maxqueue = 0;
1332 defproxy.defsrv.minconn = 0;
1333 defproxy.defsrv.maxconn = 0;
1334 defproxy.defsrv.slowstart = 0;
1335 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1336 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1337 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338}
1339
Willy Tarreauade5ec42010-01-28 19:33:49 +01001340
1341static int create_cond_regex_rule(const char *file, int line,
1342 struct proxy *px, int dir, int action, int flags,
1343 const char *cmd, const char *reg, const char *repl,
1344 const char **cond_start)
1345{
1346 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001347 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001348 const char *err;
1349 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001350 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001351
1352 if (px == &defproxy) {
1353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto err;
1356 }
1357
1358 if (*reg == 0) {
1359 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1365 err_code |= ERR_WARN;
1366
Willy Tarreau5321c422010-01-28 20:35:13 +01001367 if (cond_start &&
1368 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001369 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1370 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1371 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001372 err_code |= ERR_ALERT | ERR_FATAL;
1373 goto err;
1374 }
1375 }
1376 else if (cond_start && **cond_start) {
1377 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1378 file, line, cmd, *cond_start);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto err;
1381 }
1382
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001383 err_code |= warnif_cond_conflicts(cond,
1384 (dir == SMP_OPT_DIR_REQ) ?
1385 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1386 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1387 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001388
Willy Tarreauade5ec42010-01-28 19:33:49 +01001389 preg = calloc(1, sizeof(regex_t));
1390 if (!preg) {
1391 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1392 err_code = ERR_ALERT | ERR_FATAL;
1393 goto err;
1394 }
1395
1396 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1397 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1398 err_code = ERR_ALERT | ERR_FATAL;
1399 goto err;
1400 }
1401
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001402 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001403 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001404 if (repl && err) {
1405 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1406 file, line, cmd, *err);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 goto err;
1409 }
1410
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001411 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001412 err_code |= ERR_WARN;
1413
Willy Tarreauf4068b62012-05-08 17:37:49 +02001414 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001415 return err_code;
1416 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001417 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001418 free(preg);
1419 return err_code;
1420}
1421
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001424 * Returns the error code, 0 if OK, or any combination of :
1425 * - ERR_ABORT: must abort ASAP
1426 * - ERR_FATAL: we can continue parsing but not start the service
1427 * - ERR_WARN: a warning has been emitted
1428 * - ERR_ALERT: an alert has been emitted
1429 * Only the two first ones can stop processing, the two others are just
1430 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001432int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1433{
1434 static struct peers *curpeers = NULL;
1435 struct peer *newpeer = NULL;
1436 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001437 struct bind_conf *bind_conf;
1438 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001439 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001440 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001441
1442 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001443 if (!*args[1]) {
1444 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001448
1449 err = invalid_char(args[1]);
1450 if (err) {
1451 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1452 file, linenum, *err, args[0], args[1]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001454 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001455 }
1456
1457 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1458 /*
1459 * If there are two proxies with the same name only following
1460 * combinations are allowed:
1461 */
1462 if (strcmp(curpeers->id, args[1]) == 0) {
1463 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1464 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1465 err_code |= ERR_WARN;
1466 }
1467 }
1468
1469 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1471 err_code |= ERR_ALERT | ERR_ABORT;
1472 goto out;
1473 }
1474
1475 curpeers->next = peers;
1476 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001477 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001478 curpeers->conf.line = linenum;
1479 curpeers->last_change = now.tv_sec;
1480 curpeers->id = strdup(args[1]);
1481 }
1482 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001483 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001484 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001485 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001486
1487 if (!*args[2]) {
1488 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1489 file, linenum, args[0]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 err = invalid_char(args[1]);
1495 if (err) {
1496 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1497 file, linenum, *err, args[1]);
1498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1503 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1504 err_code |= ERR_ALERT | ERR_ABORT;
1505 goto out;
1506 }
1507
1508 /* the peers are linked backwards first */
1509 curpeers->count++;
1510 newpeer->next = curpeers->remote;
1511 curpeers->remote = newpeer;
1512 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001513 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001514 newpeer->conf.line = linenum;
1515
1516 newpeer->last_change = now.tv_sec;
1517 newpeer->id = strdup(args[1]);
1518
Willy Tarreau902636f2013-03-10 19:44:48 +01001519 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001520 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001521 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001524 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001525
1526 proto = protocol_by_family(sk->ss_family);
1527 if (!proto || !proto->connect) {
1528 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1529 file, linenum, args[0], args[1]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001533
1534 if (port1 != port2) {
1535 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1536 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
1540
Willy Tarreau2aa38802013-02-20 19:20:59 +01001541 if (!port1) {
1542 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1543 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001547
Emeric Brun32da3c42010-09-23 18:39:19 +02001548 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001549 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001550 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001551 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001552
Emeric Brun32da3c42010-09-23 18:39:19 +02001553 if (strcmp(newpeer->id, localpeer) == 0) {
1554 /* Current is local peer, it define a frontend */
1555 newpeer->local = 1;
1556
1557 if (!curpeers->peers_fe) {
1558 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1559 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1560 err_code |= ERR_ALERT | ERR_ABORT;
1561 goto out;
1562 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001563
Willy Tarreau237250c2011-07-29 01:49:03 +02001564 init_new_proxy(curpeers->peers_fe);
1565 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001566
1567 curpeers->peers_fe->last_change = now.tv_sec;
1568 curpeers->peers_fe->id = strdup(args[1]);
1569 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001570 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001571 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1572 curpeers->peers_fe->timeout.connect = 5000;
1573 curpeers->peers_fe->accept = peer_accept;
1574 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001575 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1576 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001577
1578 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1579
Willy Tarreau902636f2013-03-10 19:44:48 +01001580 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1581 if (errmsg && *errmsg) {
1582 indent_msg(&errmsg, 2);
1583 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001584 }
1585 else
1586 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1587 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001588 err_code |= ERR_FATAL;
1589 goto out;
1590 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001591
1592 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1593 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1594 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1595 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1596 l->accept = session_accept;
1597 l->handler = process_session;
1598 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1599 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1600 global.maxsock += l->maxconn;
1601 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001602 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001603 else {
1604 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1605 file, linenum, args[0], args[1],
1606 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1607 err_code |= ERR_FATAL;
1608 goto out;
1609 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001610 }
1611 } /* neither "peer" nor "peers" */
1612 else if (*args[0] != 0) {
1613 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1614 err_code |= ERR_ALERT | ERR_FATAL;
1615 goto out;
1616 }
1617
1618out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001619 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001620 return err_code;
1621}
1622
1623
Willy Tarreau3842f002009-06-14 11:39:52 +02001624int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625{
1626 static struct proxy *curproxy = NULL;
1627 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001628 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001629 int rc;
1630 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001631 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001632 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001633 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001634 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001635 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636
Willy Tarreau977b8e42006-12-29 14:19:17 +01001637 if (!strcmp(args[0], "listen"))
1638 rc = PR_CAP_LISTEN;
1639 else if (!strcmp(args[0], "frontend"))
1640 rc = PR_CAP_FE | PR_CAP_RS;
1641 else if (!strcmp(args[0], "backend"))
1642 rc = PR_CAP_BE | PR_CAP_RS;
1643 else if (!strcmp(args[0], "ruleset"))
1644 rc = PR_CAP_RS;
1645 else
1646 rc = PR_CAP_NONE;
1647
1648 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 if (!*args[1]) {
1650 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1651 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_ABORT;
1654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001656
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001657 err = invalid_char(args[1]);
1658 if (err) {
1659 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1660 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001661 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001662 }
1663
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001664 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1665 /*
1666 * If there are two proxies with the same name only following
1667 * combinations are allowed:
1668 *
1669 * listen backend frontend ruleset
1670 * listen - - - -
1671 * backend - - OK -
1672 * frontend - OK - -
1673 * ruleset - - - -
1674 */
1675
1676 if (!strcmp(curproxy->id, args[1]) &&
1677 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1678 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001679 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1680 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1681 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001682 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001683 }
1684 }
1685
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1687 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_ABORT;
1689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001691
Willy Tarreau97cb7802010-01-03 20:23:58 +01001692 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693 curproxy->next = proxy;
1694 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001695 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1696 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001697 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001699 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700
1701 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001703 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001704
Willy Tarreau4348fad2012-09-20 16:48:07 +02001705 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1706
Willy Tarreau902636f2013-03-10 19:44:48 +01001707 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1708 if (errmsg && *errmsg) {
1709 indent_msg(&errmsg, 2);
1710 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001711 }
1712 else
1713 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1714 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001715 err_code |= ERR_FATAL;
1716 goto out;
1717 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001718
Willy Tarreau4348fad2012-09-20 16:48:07 +02001719 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001720 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 }
1723
1724 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001725 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001726 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001727
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001730 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001731 curproxy->no_options = defproxy.no_options;
1732 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001733 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001734 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001735 curproxy->except_net = defproxy.except_net;
1736 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001737 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001738 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001740 if (defproxy.fwdfor_hdr_len) {
1741 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1742 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1743 }
1744
Willy Tarreaub86db342009-11-30 11:50:16 +01001745 if (defproxy.orgto_hdr_len) {
1746 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1747 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1748 }
1749
Mark Lamourinec2247f02012-01-04 13:02:01 -05001750 if (defproxy.server_id_hdr_len) {
1751 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1752 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1753 }
1754
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 if (curproxy->cap & PR_CAP_FE) {
1756 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001757 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001758 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001759
1760 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001761 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1762 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763
1764 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766
Willy Tarreau977b8e42006-12-29 14:19:17 +01001767 if (curproxy->cap & PR_CAP_BE) {
1768 curproxy->fullconn = defproxy.fullconn;
1769 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001771 if (defproxy.check_req) {
1772 curproxy->check_req = calloc(1, defproxy.check_len);
1773 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1774 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001775 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001777 if (defproxy.expect_str) {
1778 curproxy->expect_str = strdup(defproxy.expect_str);
1779 if (defproxy.expect_regex) {
1780 /* note: this regex is known to be valid */
1781 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1782 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1783 }
1784 }
1785
Willy Tarreau67402132012-05-31 20:40:20 +02001786 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 if (defproxy.cookie_name)
1788 curproxy->cookie_name = strdup(defproxy.cookie_name);
1789 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001790 if (defproxy.cookie_domain)
1791 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001792
Willy Tarreau31936852010-10-06 16:59:56 +02001793 if (defproxy.cookie_maxidle)
1794 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1795
1796 if (defproxy.cookie_maxlife)
1797 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1798
Emeric Brun647caf12009-06-30 17:57:00 +02001799 if (defproxy.rdp_cookie_name)
1800 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1801 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1802
Willy Tarreau01732802007-11-01 22:48:15 +01001803 if (defproxy.url_param_name)
1804 curproxy->url_param_name = strdup(defproxy.url_param_name);
1805 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001806
Benoitaffb4812009-03-25 13:02:10 +01001807 if (defproxy.hh_name)
1808 curproxy->hh_name = strdup(defproxy.hh_name);
1809 curproxy->hh_len = defproxy.hh_len;
1810 curproxy->hh_match_domain = defproxy.hh_match_domain;
1811
Willy Tarreauef9a3602012-12-08 22:29:20 +01001812 if (defproxy.conn_src.iface_name)
1813 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1814 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1815 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001818 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001819 if (defproxy.capture_name)
1820 curproxy->capture_name = strdup(defproxy.capture_name);
1821 curproxy->capture_namelen = defproxy.capture_namelen;
1822 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001823 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001824
Willy Tarreau977b8e42006-12-29 14:19:17 +01001825 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001826 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001827 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001828 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001829 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001830 curproxy->uri_auth = defproxy.uri_auth;
1831 curproxy->mon_net = defproxy.mon_net;
1832 curproxy->mon_mask = defproxy.mon_mask;
1833 if (defproxy.monitor_uri)
1834 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1835 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001836 if (defproxy.defbe.name)
1837 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001838
1839 /* get either a pointer to the logformat string or a copy of it */
1840 curproxy->logformat_string = defproxy.logformat_string;
1841 if (curproxy->logformat_string &&
1842 curproxy->logformat_string != default_http_log_format &&
1843 curproxy->logformat_string != default_tcp_log_format &&
1844 curproxy->logformat_string != clf_http_log_format)
1845 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001846 }
1847
1848 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001849 curproxy->timeout.connect = defproxy.timeout.connect;
1850 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001851 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001852 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001853 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001854 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001855 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001856 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001857 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001858 }
1859
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001861
1862 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001863 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001864 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001865 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001866 LIST_INIT(&node->list);
1867 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1868 }
1869
Willy Tarreau196729e2012-05-31 19:30:26 +02001870 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1871 if (curproxy->uniqueid_format_string)
1872 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001873
1874 /* copy default header unique id */
1875 if (defproxy.header_unique_id)
1876 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1877
William Lallemand82fe75c2012-10-23 10:25:10 +02001878 /* default compression options */
1879 if (defproxy.comp != NULL) {
1880 curproxy->comp = calloc(1, sizeof(struct comp));
1881 curproxy->comp->algos = defproxy.comp->algos;
1882 curproxy->comp->types = defproxy.comp->types;
1883 }
1884
Willy Tarreaubaaee002006-06-26 02:48:02 +02001885 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001886 curproxy->conf.used_listener_id = EB_ROOT;
1887 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001888
Willy Tarreau93893792009-07-23 13:19:11 +02001889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 }
1891 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1892 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001893 /* FIXME-20070101: we should do this too at the end of the
1894 * config parsing to free all default values.
1895 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001896 free(defproxy.check_req);
1897 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001898 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001899 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001900 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001901 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001902 free(defproxy.capture_name);
1903 free(defproxy.monitor_uri);
1904 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001905 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001906 free(defproxy.fwdfor_hdr_name);
1907 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001908 free(defproxy.orgto_hdr_name);
1909 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001910 free(defproxy.server_id_hdr_name);
1911 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001912 free(defproxy.expect_str);
1913 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001914
Willy Tarreau39b06652012-06-01 10:58:06 +02001915 if (defproxy.logformat_string != default_http_log_format &&
1916 defproxy.logformat_string != default_tcp_log_format &&
1917 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001918 free(defproxy.logformat_string);
1919
1920 free(defproxy.uniqueid_format_string);
1921
Willy Tarreaua534fea2008-08-03 12:19:50 +02001922 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001923 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001924
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 /* we cannot free uri_auth because it might already be used */
1926 init_default_instance();
1927 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001928 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1929 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001930 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 }
1933 else if (curproxy == NULL) {
1934 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001938
1939 /* update the current file and line being parsed */
1940 curproxy->conf.args.file = curproxy->conf.file;
1941 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001942
1943 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001945 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001946 int cur_arg;
1947
Willy Tarreaubaaee002006-06-26 02:48:02 +02001948 if (curproxy == &defproxy) {
1949 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001953 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955
Willy Tarreau24709282013-03-10 21:32:12 +01001956 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001957 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001959 err_code |= ERR_ALERT | ERR_FATAL;
1960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001962
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001963 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001964
1965 /* use default settings for unix sockets */
1966 bind_conf->ux.uid = global.unix_bind.ux.uid;
1967 bind_conf->ux.gid = global.unix_bind.ux.gid;
1968 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001969
1970 /* NOTE: the following line might create several listeners if there
1971 * are comma-separated IPs or port ranges. So all further processing
1972 * will have to be applied to all listeners created after last_listen.
1973 */
Willy Tarreau902636f2013-03-10 19:44:48 +01001974 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
1975 if (errmsg && *errmsg) {
1976 indent_msg(&errmsg, 2);
1977 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001978 }
1979 else
1980 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1981 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001982 err_code |= ERR_ALERT | ERR_FATAL;
1983 goto out;
1984 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001985
Willy Tarreau4348fad2012-09-20 16:48:07 +02001986 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1987 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001988 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001989 }
1990
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001991 cur_arg = 2;
1992 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001993 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001994 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001995 char *err;
1996
Willy Tarreau26982662012-09-12 23:17:10 +02001997 kw = bind_find_kw(args[cur_arg]);
1998 if (kw) {
1999 char *err = NULL;
2000 int code;
2001
2002 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002003 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2004 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002005 cur_arg += 1 + kw->skip ;
2006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
2008 }
2009
Willy Tarreau4348fad2012-09-20 16:48:07 +02002010 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002011 err_code |= code;
2012
2013 if (code) {
2014 if (err && *err) {
2015 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002016 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002017 }
2018 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002019 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2020 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002021 if (code & ERR_FATAL) {
2022 free(err);
2023 cur_arg += 1 + kw->skip;
2024 goto out;
2025 }
2026 }
2027 free(err);
2028 cur_arg += 1 + kw->skip;
2029 continue;
2030 }
2031
Willy Tarreau8638f482012-09-18 18:01:17 +02002032 err = NULL;
2033 if (!bind_dumped) {
2034 bind_dump_kws(&err);
2035 indent_msg(&err, 4);
2036 bind_dumped = 1;
2037 }
2038
2039 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2040 file, linenum, args[0], args[1], args[cur_arg],
2041 err ? " Registered keywords :" : "", err ? err : "");
2042 free(err);
2043
Willy Tarreau93893792009-07-23 13:19:11 +02002044 err_code |= ERR_ALERT | ERR_FATAL;
2045 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002046 }
Willy Tarreau93893792009-07-23 13:19:11 +02002047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002048 }
2049 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2050 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2051 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002055 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002056 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002058
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 /* flush useless bits */
2060 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002063 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002066
Willy Tarreau1c47f852006-07-09 08:22:27 +02002067 if (!*args[1]) {
2068 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2069 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002070 err_code |= ERR_ALERT | ERR_FATAL;
2071 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002072 }
2073
Willy Tarreaua534fea2008-08-03 12:19:50 +02002074 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002075 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002076 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002077 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002078 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2079
Willy Tarreau93893792009-07-23 13:19:11 +02002080 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2083 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2084 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2085 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2086 else {
2087 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002088 err_code |= ERR_ALERT | ERR_FATAL;
2089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002090 }
2091 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002092 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002093 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002094
2095 if (curproxy == &defproxy) {
2096 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2097 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002100 }
2101
2102 if (!*args[1]) {
2103 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2104 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002107 }
2108
2109 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002110 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002111
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002112 if (curproxy->uuid <= 0) {
2113 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002114 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002115 err_code |= ERR_ALERT | ERR_FATAL;
2116 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002117 }
2118
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002119 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2120 if (node) {
2121 struct proxy *target = container_of(node, struct proxy, conf.id);
2122 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2123 file, linenum, proxy_type_str(curproxy), curproxy->id,
2124 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2125 err_code |= ERR_ALERT | ERR_FATAL;
2126 goto out;
2127 }
2128 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002129 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002130 else if (!strcmp(args[0], "description")) {
2131 int i, len=0;
2132 char *d;
2133
Cyril Bonté99ed3272010-01-24 23:29:44 +01002134 if (curproxy == &defproxy) {
2135 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2136 file, linenum, args[0]);
2137 err_code |= ERR_ALERT | ERR_FATAL;
2138 goto out;
2139 }
2140
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002141 if (!*args[1]) {
2142 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2143 file, linenum, args[0]);
2144 return -1;
2145 }
2146
2147 for(i=1; *args[i]; i++)
2148 len += strlen(args[i])+1;
2149
2150 d = (char *)calloc(1, len);
2151 curproxy->desc = d;
2152
2153 d += sprintf(d, "%s", args[1]);
2154 for(i=2; *args[i]; i++)
2155 d += sprintf(d, " %s", args[i]);
2156
2157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2159 curproxy->state = PR_STSTOPPED;
2160 }
2161 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2162 curproxy->state = PR_STNEW;
2163 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002164 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2165 int cur_arg = 1;
2166 unsigned int set = 0;
2167
2168 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002169 unsigned int low, high;
2170
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002171 if (strcmp(args[cur_arg], "all") == 0) {
2172 set = 0;
2173 break;
2174 }
2175 else if (strcmp(args[cur_arg], "odd") == 0) {
2176 set |= 0x55555555;
2177 }
2178 else if (strcmp(args[cur_arg], "even") == 0) {
2179 set |= 0xAAAAAAAA;
2180 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002181 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002182 char *dash = strchr(args[cur_arg], '-');
2183
2184 low = high = str2uic(args[cur_arg]);
2185 if (dash)
2186 high = str2uic(dash + 1);
2187
2188 if (high < low) {
2189 unsigned int swap = low;
2190 low = high;
2191 high = swap;
2192 }
2193
2194 if (low < 1 || high > 32) {
2195 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002199 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002200
2201 if (high > global.nbproc) {
2202 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2203 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002205 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002206 while (low <= high)
2207 set |= 1 << (low++ - 1);
2208 }
2209 else {
2210 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2211 file, linenum, args[0]);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002214 }
2215 cur_arg++;
2216 }
2217 curproxy->bind_proc = set;
2218 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002219 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002220 if (curproxy == &defproxy) {
2221 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002224 }
2225
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002226 err = invalid_char(args[1]);
2227 if (err) {
2228 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2229 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002231 }
2232
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002233 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002234 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2235 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002238 }
2239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2241 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242
Willy Tarreau977b8e42006-12-29 14:19:17 +01002243 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002244 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002245
Willy Tarreaubaaee002006-06-26 02:48:02 +02002246 if (*(args[1]) == 0) {
2247 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2248 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002252
Willy Tarreau67402132012-05-31 20:40:20 +02002253 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002254 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002255 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002256 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 curproxy->cookie_name = strdup(args[1]);
2258 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002259
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 cur_arg = 2;
2261 while (*(args[cur_arg])) {
2262 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002263 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 }
2265 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002266 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 }
2268 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002269 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 }
2271 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002272 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002273 }
2274 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002275 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002277 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002278 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002281 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002283 else if (!strcmp(args[cur_arg], "httponly")) {
2284 curproxy->ck_opts |= PR_CK_HTTPONLY;
2285 }
2286 else if (!strcmp(args[cur_arg], "secure")) {
2287 curproxy->ck_opts |= PR_CK_SECURE;
2288 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002289 else if (!strcmp(args[cur_arg], "domain")) {
2290 if (!*args[cur_arg + 1]) {
2291 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2292 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002295 }
2296
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002297 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002298 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002299 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2300 " dots nor does not start with a dot."
2301 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002302 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002303 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002304 }
2305
2306 err = invalid_domainchar(args[cur_arg + 1]);
2307 if (err) {
2308 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2309 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002312 }
2313
Willy Tarreau68a897b2009-12-03 23:28:34 +01002314 if (!curproxy->cookie_domain) {
2315 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2316 } else {
2317 /* one domain was already specified, add another one by
2318 * building the string which will be returned along with
2319 * the cookie.
2320 */
2321 char *new_ptr;
2322 int new_len = strlen(curproxy->cookie_domain) +
2323 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2324 new_ptr = malloc(new_len);
2325 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2326 free(curproxy->cookie_domain);
2327 curproxy->cookie_domain = new_ptr;
2328 }
Willy Tarreau31936852010-10-06 16:59:56 +02002329 cur_arg++;
2330 }
2331 else if (!strcmp(args[cur_arg], "maxidle")) {
2332 unsigned int maxidle;
2333 const char *res;
2334
2335 if (!*args[cur_arg + 1]) {
2336 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2337 file, linenum, args[cur_arg]);
2338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
2340 }
2341
2342 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2343 if (res) {
2344 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2345 file, linenum, *res, args[cur_arg]);
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
2348 }
2349 curproxy->cookie_maxidle = maxidle;
2350 cur_arg++;
2351 }
2352 else if (!strcmp(args[cur_arg], "maxlife")) {
2353 unsigned int maxlife;
2354 const char *res;
2355
2356 if (!*args[cur_arg + 1]) {
2357 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2358 file, linenum, args[cur_arg]);
2359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
2361 }
2362
2363 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2364 if (res) {
2365 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2366 file, linenum, *res, args[cur_arg]);
2367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
2369 }
2370 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002371 cur_arg++;
2372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002374 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 +02002375 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }
2379 cur_arg++;
2380 }
Willy Tarreau67402132012-05-31 20:40:20 +02002381 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2383 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002384 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 }
2386
Willy Tarreau67402132012-05-31 20:40:20 +02002387 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2389 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002390 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002392
Willy Tarreau67402132012-05-31 20:40:20 +02002393 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002394 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2395 file, linenum);
2396 err_code |= ERR_ALERT | ERR_FATAL;
2397 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002399 else if (!strcmp(args[0], "persist")) { /* persist */
2400 if (*(args[1]) == 0) {
2401 Alert("parsing [%s:%d] : missing persist method.\n",
2402 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002405 }
2406
2407 if (!strncmp(args[1], "rdp-cookie", 10)) {
2408 curproxy->options2 |= PR_O2_RDPC_PRST;
2409
Emeric Brunb982a3d2010-01-04 15:45:53 +01002410 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002411 const char *beg, *end;
2412
2413 beg = args[1] + 11;
2414 end = strchr(beg, ')');
2415
2416 if (!end || end == beg) {
2417 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2418 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002421 }
2422
2423 free(curproxy->rdp_cookie_name);
2424 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2425 curproxy->rdp_cookie_len = end-beg;
2426 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002427 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002428 free(curproxy->rdp_cookie_name);
2429 curproxy->rdp_cookie_name = strdup("msts");
2430 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2431 }
2432 else { /* syntax */
2433 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2434 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002437 }
2438 }
2439 else {
2440 Alert("parsing [%s:%d] : unknown persist method.\n",
2441 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002444 }
2445 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002447 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002449 if (curproxy == &defproxy) {
2450 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
2453 }
2454
Willy Tarreau977b8e42006-12-29 14:19:17 +01002455 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002457
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002459 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 }
2464 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002465 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 curproxy->appsession_name = strdup(args[1]);
2467 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2468 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002469 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2470 if (err) {
2471 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2472 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_FATAL;
2474 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002475 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002476 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002477
Willy Tarreau51041c72007-09-09 21:56:53 +02002478 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2479 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_ABORT;
2481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002483
2484 cur_arg = 6;
2485 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002486 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2487 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002488 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002489 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002490 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002491 } else if (!strcmp(args[cur_arg], "prefix")) {
2492 curproxy->options2 |= PR_O2_AS_PFX;
2493 } else if (!strcmp(args[cur_arg], "mode")) {
2494 if (!*args[cur_arg + 1]) {
2495 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2496 file, linenum, args[0], args[cur_arg]);
2497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
2499 }
2500
2501 cur_arg++;
2502 if (!strcmp(args[cur_arg], "query-string")) {
2503 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2504 curproxy->options2 |= PR_O2_AS_M_QS;
2505 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2506 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2507 curproxy->options2 |= PR_O2_AS_M_PP;
2508 } else {
2509 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
2512 }
2513 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002514 cur_arg++;
2515 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 } /* Url App Session */
2517 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002518 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002520
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002522 if (curproxy == &defproxy) {
2523 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
2526 }
2527
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 if (*(args[4]) == 0) {
2529 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2530 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002534 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 curproxy->capture_name = strdup(args[2]);
2536 curproxy->capture_namelen = strlen(curproxy->capture_name);
2537 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 curproxy->to_log |= LW_COOKIE;
2539 }
2540 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2541 struct cap_hdr *hdr;
2542
2543 if (curproxy == &defproxy) {
2544 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 +02002545 err_code |= ERR_ALERT | ERR_FATAL;
2546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 }
2548
2549 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2550 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2551 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 }
2555
2556 hdr = calloc(sizeof(struct cap_hdr), 1);
2557 hdr->next = curproxy->req_cap;
2558 hdr->name = strdup(args[3]);
2559 hdr->namelen = strlen(args[3]);
2560 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002561 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 hdr->index = curproxy->nb_req_cap++;
2563 curproxy->req_cap = hdr;
2564 curproxy->to_log |= LW_REQHDR;
2565 }
2566 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2567 struct cap_hdr *hdr;
2568
2569 if (curproxy == &defproxy) {
2570 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 +02002571 err_code |= ERR_ALERT | ERR_FATAL;
2572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 }
2574
2575 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2576 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2577 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
2581 hdr = calloc(sizeof(struct cap_hdr), 1);
2582 hdr->next = curproxy->rsp_cap;
2583 hdr->name = strdup(args[3]);
2584 hdr->namelen = strlen(args[3]);
2585 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002586 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 hdr->index = curproxy->nb_rsp_cap++;
2588 curproxy->rsp_cap = hdr;
2589 curproxy->to_log |= LW_RSPHDR;
2590 }
2591 else {
2592 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2593 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
2597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002599 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002600 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 if (*(args[1]) == 0) {
2603 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2604 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 }
2608 curproxy->conn_retries = atol(args[1]);
2609 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002610 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002611 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002612
2613 if (curproxy == &defproxy) {
2614 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
2617 }
2618
Willy Tarreau20b0de52012-12-24 15:45:22 +01002619 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2620 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2621 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2622 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2623 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2624 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 +01002625 file, linenum, args[0]);
2626 err_code |= ERR_WARN;
2627 }
2628
Willy Tarreauff011f22011-01-06 17:51:27 +01002629 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002630
Willy Tarreauff011f22011-01-06 17:51:27 +01002631 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002632 err_code |= ERR_ALERT | ERR_ABORT;
2633 goto out;
2634 }
2635
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002636 err_code |= warnif_cond_conflicts(rule->cond,
2637 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2638 file, linenum);
2639
Willy Tarreauff011f22011-01-06 17:51:27 +01002640 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002641 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002642 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2643 /* set the header name and length into the proxy structure */
2644 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2645 err_code |= ERR_WARN;
2646
2647 if (!*args[1]) {
2648 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2649 file, linenum, args[0]);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653
2654 /* set the desired header name */
2655 free(curproxy->server_id_hdr_name);
2656 curproxy->server_id_hdr_name = strdup(args[1]);
2657 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2658 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002659 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002660 if (curproxy == &defproxy) {
2661 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002664 }
2665
Willy Tarreauef6494c2010-01-28 17:12:36 +01002666 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002667 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2668 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002671 }
2672
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002673 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2674 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2675 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002678 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002679
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002680 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002681 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002682 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002683 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002684 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002685
Cyril Bonté99ed3272010-01-24 23:29:44 +01002686 if (curproxy == &defproxy) {
2687 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2688 err_code |= ERR_ALERT | ERR_FATAL;
2689 goto out;
2690 }
2691
Willy Tarreau4baae242012-12-27 12:00:31 +01002692 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2693 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2694 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002695 err_code |= ERR_ALERT | ERR_FATAL;
2696 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002697 }
2698
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002699 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002700 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002701 err_code |= warnif_cond_conflicts(rule->cond,
2702 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2703 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002704 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002705 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002706 struct switching_rule *rule;
2707
Willy Tarreaub099aca2008-10-12 17:26:37 +02002708 if (curproxy == &defproxy) {
2709 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002712 }
2713
Willy Tarreau55ea7572007-06-17 19:56:27 +02002714 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002716
2717 if (*(args[1]) == 0) {
2718 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002721 }
2722
Willy Tarreauef6494c2010-01-28 17:12:36 +01002723 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002724 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2725 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002728 }
2729
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002730 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2731 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2732 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002735 }
2736
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002737 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002738
Willy Tarreau55ea7572007-06-17 19:56:27 +02002739 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2740 rule->cond = cond;
2741 rule->be.name = strdup(args[1]);
2742 LIST_INIT(&rule->list);
2743 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2744 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002745 else if (strcmp(args[0], "use-server") == 0) {
2746 struct server_rule *rule;
2747
2748 if (curproxy == &defproxy) {
2749 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
2752 }
2753
2754 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2755 err_code |= ERR_WARN;
2756
2757 if (*(args[1]) == 0) {
2758 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
2761 }
2762
2763 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2764 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2765 file, linenum, args[0]);
2766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002770 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2771 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2772 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
2775 }
2776
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002777 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002778
2779 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2780 rule->cond = cond;
2781 rule->srv.name = strdup(args[1]);
2782 LIST_INIT(&rule->list);
2783 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2784 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2785 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002786 else if ((!strcmp(args[0], "force-persist")) ||
2787 (!strcmp(args[0], "ignore-persist"))) {
2788 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002789
2790 if (curproxy == &defproxy) {
2791 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
2794 }
2795
2796 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2797 err_code |= ERR_WARN;
2798
Willy Tarreauef6494c2010-01-28 17:12:36 +01002799 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002800 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2801 file, linenum, args[0]);
2802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
2804 }
2805
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002806 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2807 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2808 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
2811 }
2812
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002813 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2814 * where force-persist is applied.
2815 */
2816 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002817
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002818 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002819 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002820 if (!strcmp(args[0], "force-persist")) {
2821 rule->type = PERSIST_TYPE_FORCE;
2822 } else {
2823 rule->type = PERSIST_TYPE_IGNORE;
2824 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002825 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002826 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002827 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002828 else if (!strcmp(args[0], "stick-table")) {
2829 int myidx = 1;
2830
Emeric Brun32da3c42010-09-23 18:39:19 +02002831 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002832 curproxy->table.type = (unsigned int)-1;
2833 while (*args[myidx]) {
2834 const char *err;
2835
2836 if (strcmp(args[myidx], "size") == 0) {
2837 myidx++;
2838 if (!*(args[myidx])) {
2839 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2840 file, linenum, args[myidx-1]);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843 }
2844 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2845 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2846 file, linenum, *err, args[myidx-1]);
2847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
2849 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002850 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002851 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002852 else if (strcmp(args[myidx], "peers") == 0) {
2853 myidx++;
2854 if (!*(args[myidx])) {
2855 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2856 file, linenum, args[myidx-1]);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859 }
2860 curproxy->table.peers.name = strdup(args[myidx++]);
2861 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002862 else if (strcmp(args[myidx], "expire") == 0) {
2863 myidx++;
2864 if (!*(args[myidx])) {
2865 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2866 file, linenum, args[myidx-1]);
2867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
2869 }
2870 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2871 if (err) {
2872 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2873 file, linenum, *err, args[myidx-1]);
2874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
2876 }
2877 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002878 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002879 }
2880 else if (strcmp(args[myidx], "nopurge") == 0) {
2881 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002882 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002883 }
2884 else if (strcmp(args[myidx], "type") == 0) {
2885 myidx++;
2886 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2887 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2888 file, linenum, args[myidx]);
2889 err_code |= ERR_ALERT | ERR_FATAL;
2890 goto out;
2891 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002892 /* myidx already points to next arg */
2893 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002894 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002895 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002896 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002897
2898 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002899 nw = args[myidx];
2900 while (*nw) {
2901 /* the "store" keyword supports a comma-separated list */
2902 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002903 sa = NULL; /* store arg */
2904 while (*nw && *nw != ',') {
2905 if (*nw == '(') {
2906 *nw = 0;
2907 sa = ++nw;
2908 while (*nw != ')') {
2909 if (!*nw) {
2910 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2911 file, linenum, args[0], cw);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915 nw++;
2916 }
2917 *nw = '\0';
2918 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002919 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002920 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002921 if (*nw)
2922 *nw++ = '\0';
2923 type = stktable_get_data_type(cw);
2924 if (type < 0) {
2925 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2926 file, linenum, args[0], cw);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
Willy Tarreauac782882010-06-20 10:41:54 +02002930
2931 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2932 switch (err) {
2933 case PE_NONE: break;
2934 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002935 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2936 file, linenum, args[0], cw);
2937 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002938 break;
2939
2940 case PE_ARG_MISSING:
2941 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2942 file, linenum, args[0], cw);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945
2946 case PE_ARG_NOT_USED:
2947 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2948 file, linenum, args[0], cw);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951
2952 default:
2953 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2954 file, linenum, args[0], cw);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002957 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002958 }
2959 myidx++;
2960 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002961 else {
2962 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2963 file, linenum, args[myidx]);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002966 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002967 }
2968
2969 if (!curproxy->table.size) {
2970 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2971 file, linenum);
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
2975
2976 if (curproxy->table.type == (unsigned int)-1) {
2977 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2978 file, linenum);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982 }
2983 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002984 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002985 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002986 int myidx = 0;
2987 const char *name = NULL;
2988 int flags;
2989
2990 if (curproxy == &defproxy) {
2991 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
2994 }
2995
2996 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2997 err_code |= ERR_WARN;
2998 goto out;
2999 }
3000
3001 myidx++;
3002 if ((strcmp(args[myidx], "store") == 0) ||
3003 (strcmp(args[myidx], "store-request") == 0)) {
3004 myidx++;
3005 flags = STK_IS_STORE;
3006 }
3007 else if (strcmp(args[myidx], "store-response") == 0) {
3008 myidx++;
3009 flags = STK_IS_STORE | STK_ON_RSP;
3010 }
3011 else if (strcmp(args[myidx], "match") == 0) {
3012 myidx++;
3013 flags = STK_IS_MATCH;
3014 }
3015 else if (strcmp(args[myidx], "on") == 0) {
3016 myidx++;
3017 flags = STK_IS_MATCH | STK_IS_STORE;
3018 }
3019 else {
3020 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
3023 }
3024
3025 if (*(args[myidx]) == 0) {
3026 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
3029 }
3030
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003031 curproxy->conf.args.ctx = ARGC_STK;
3032 expr = sample_parse_expr(args, &myidx, trash.str, trash.size, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003033 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003034 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
3037 }
3038
3039 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003040 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3041 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3042 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003043 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003044 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 goto out;
3046 }
3047 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003048 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3049 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3050 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003051 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003052 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003053 goto out;
3054 }
3055 }
3056
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003057 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003058 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003059
Emeric Brunb982a3d2010-01-04 15:45:53 +01003060 if (strcmp(args[myidx], "table") == 0) {
3061 myidx++;
3062 name = args[myidx++];
3063 }
3064
Willy Tarreauef6494c2010-01-28 17:12:36 +01003065 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003066 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3067 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3068 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003069 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003070 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003071 goto out;
3072 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003073 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003074 else if (*(args[myidx])) {
3075 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3076 file, linenum, args[0], args[myidx]);
3077 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003078 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003079 goto out;
3080 }
Emeric Brun97679e72010-09-23 17:56:44 +02003081 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003082 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003083 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003084 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003085
Emeric Brunb982a3d2010-01-04 15:45:53 +01003086 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3087 rule->cond = cond;
3088 rule->expr = expr;
3089 rule->flags = flags;
3090 rule->table.name = name ? strdup(name) : NULL;
3091 LIST_INIT(&rule->list);
3092 if (flags & STK_ON_RSP)
3093 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3094 else
3095 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003098 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003099 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003100
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3102 curproxy->uri_auth = NULL; /* we must detach from the default config */
3103
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003104 if (!*args[1]) {
3105 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003106 } else if (!strcmp(args[1], "admin")) {
3107 struct stats_admin_rule *rule;
3108
3109 if (curproxy == &defproxy) {
3110 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
3113 }
3114
3115 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3116 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3117 err_code |= ERR_ALERT | ERR_ABORT;
3118 goto out;
3119 }
3120
3121 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3122 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3123 file, linenum, args[0], args[1]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003127 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3128 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3129 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
3133
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003134 err_code |= warnif_cond_conflicts(cond,
3135 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3136 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003137
3138 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3139 rule->cond = cond;
3140 LIST_INIT(&rule->list);
3141 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 } else if (!strcmp(args[1], "uri")) {
3143 if (*(args[2]) == 0) {
3144 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3148 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003149 err_code |= ERR_ALERT | ERR_ABORT;
3150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 }
3152 } else if (!strcmp(args[1], "realm")) {
3153 if (*(args[2]) == 0) {
3154 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3158 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003159 err_code |= ERR_ALERT | ERR_ABORT;
3160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003162 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003163 unsigned interval;
3164
3165 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3166 if (err) {
3167 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3168 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003169 err_code |= ERR_ALERT | ERR_FATAL;
3170 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003171 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3172 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003173 err_code |= ERR_ALERT | ERR_ABORT;
3174 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003175 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003176 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003177 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003178
3179 if (curproxy == &defproxy) {
3180 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
3183 }
3184
3185 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3186 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3187 err_code |= ERR_ALERT | ERR_ABORT;
3188 goto out;
3189 }
3190
Willy Tarreauff011f22011-01-06 17:51:27 +01003191 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3192 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003193 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3194 file, linenum, args[0]);
3195 err_code |= ERR_WARN;
3196 }
3197
Willy Tarreauff011f22011-01-06 17:51:27 +01003198 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003199
Willy Tarreauff011f22011-01-06 17:51:27 +01003200 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003201 err_code |= ERR_ALERT | ERR_ABORT;
3202 goto out;
3203 }
3204
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003205 err_code |= warnif_cond_conflicts(rule->cond,
3206 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3207 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003208 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003209
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 } else if (!strcmp(args[1], "auth")) {
3211 if (*(args[2]) == 0) {
3212 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3216 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003217 err_code |= ERR_ALERT | ERR_ABORT;
3218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219 }
3220 } else if (!strcmp(args[1], "scope")) {
3221 if (*(args[2]) == 0) {
3222 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3226 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_ABORT;
3228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 }
3230 } else if (!strcmp(args[1], "enable")) {
3231 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3232 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_ABORT;
3234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003236 } else if (!strcmp(args[1], "hide-version")) {
3237 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3238 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_ABORT;
3240 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003241 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003242 } else if (!strcmp(args[1], "show-legends")) {
3243 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3244 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3245 err_code |= ERR_ALERT | ERR_ABORT;
3246 goto out;
3247 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003248 } else if (!strcmp(args[1], "show-node")) {
3249
3250 if (*args[2]) {
3251 int i;
3252 char c;
3253
3254 for (i=0; args[2][i]; i++) {
3255 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003256 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3257 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003258 break;
3259 }
3260
3261 if (!i || args[2][i]) {
3262 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3263 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3264 file, linenum, args[0], args[1]);
3265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
3267 }
3268 }
3269
3270 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3271 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3272 err_code |= ERR_ALERT | ERR_ABORT;
3273 goto out;
3274 }
3275 } else if (!strcmp(args[1], "show-desc")) {
3276 char *desc = NULL;
3277
3278 if (*args[2]) {
3279 int i, len=0;
3280 char *d;
3281
3282 for(i=2; *args[i]; i++)
3283 len += strlen(args[i])+1;
3284
3285 desc = d = (char *)calloc(1, len);
3286
3287 d += sprintf(d, "%s", args[2]);
3288 for(i=3; *args[i]; i++)
3289 d += sprintf(d, " %s", args[i]);
3290 }
3291
3292 if (!*args[2] && !global.desc)
3293 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3294 file, linenum, args[1]);
3295 else {
3296 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3297 free(desc);
3298 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3299 err_code |= ERR_ALERT | ERR_ABORT;
3300 goto out;
3301 }
3302 free(desc);
3303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003305stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003306 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 +01003307 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
3311 }
3312 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003313 int optnum;
3314
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003315 if (*(args[1]) == '\0') {
3316 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3317 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003321
3322 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3323 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003324 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3325 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3326 file, linenum, cfg_opts[optnum].name);
3327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
3329 }
Willy Tarreau93893792009-07-23 13:19:11 +02003330 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3331 err_code |= ERR_WARN;
3332 goto out;
3333 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003334
Willy Tarreau3842f002009-06-14 11:39:52 +02003335 curproxy->no_options &= ~cfg_opts[optnum].val;
3336 curproxy->options &= ~cfg_opts[optnum].val;
3337
3338 switch (kwm) {
3339 case KWM_STD:
3340 curproxy->options |= cfg_opts[optnum].val;
3341 break;
3342 case KWM_NO:
3343 curproxy->no_options |= cfg_opts[optnum].val;
3344 break;
3345 case KWM_DEF: /* already cleared */
3346 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003347 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003348
Willy Tarreau93893792009-07-23 13:19:11 +02003349 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003350 }
3351 }
3352
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003353 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3354 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003355 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3356 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3357 file, linenum, cfg_opts2[optnum].name);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
Willy Tarreau93893792009-07-23 13:19:11 +02003361 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3362 err_code |= ERR_WARN;
3363 goto out;
3364 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003365
Willy Tarreau3842f002009-06-14 11:39:52 +02003366 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3367 curproxy->options2 &= ~cfg_opts2[optnum].val;
3368
3369 switch (kwm) {
3370 case KWM_STD:
3371 curproxy->options2 |= cfg_opts2[optnum].val;
3372 break;
3373 case KWM_NO:
3374 curproxy->no_options2 |= cfg_opts2[optnum].val;
3375 break;
3376 case KWM_DEF: /* already cleared */
3377 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003378 }
Willy Tarreau93893792009-07-23 13:19:11 +02003379 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003380 }
3381 }
3382
Willy Tarreau3842f002009-06-14 11:39:52 +02003383 if (kwm != KWM_STD) {
3384 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003385 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003388 }
3389
Emeric Brun3a058f32009-06-30 18:26:00 +02003390 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003391 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003393 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003394 if (*(args[2]) != '\0') {
3395 if (!strcmp(args[2], "clf")) {
3396 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003397 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003398 } else {
3399 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003402 }
3403 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003404 if (curproxy->logformat_string != default_http_log_format &&
3405 curproxy->logformat_string != default_tcp_log_format &&
3406 curproxy->logformat_string != clf_http_log_format)
3407 free(curproxy->logformat_string);
3408 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003409 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003410 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003412 if (curproxy->logformat_string != default_http_log_format &&
3413 curproxy->logformat_string != default_tcp_log_format &&
3414 curproxy->logformat_string != clf_http_log_format)
3415 free(curproxy->logformat_string);
3416 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 else if (!strcmp(args[1], "tcpka")) {
3419 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003420 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003421 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003422
3423 if (curproxy->cap & PR_CAP_FE)
3424 curproxy->options |= PR_O_TCP_CLI_KA;
3425 if (curproxy->cap & PR_CAP_BE)
3426 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 }
3428 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003429 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_WARN;
3431
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003433 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003434 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003435 curproxy->options2 &= ~PR_O2_CHK_ANY;
3436 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 if (!*args[2]) { /* no argument */
3438 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3439 curproxy->check_len = strlen(DEF_CHECK_REQ);
3440 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003441 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 curproxy->check_req = (char *)malloc(reqlen);
3443 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003444 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003446 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 if (*args[4])
3448 reqlen += strlen(args[4]);
3449 else
3450 reqlen += strlen("HTTP/1.0");
3451
3452 curproxy->check_req = (char *)malloc(reqlen);
3453 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003454 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003456 }
3457 else if (!strcmp(args[1], "ssl-hello-chk")) {
3458 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003459 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003460 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003461
Willy Tarreaua534fea2008-08-03 12:19:50 +02003462 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003463 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003464 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003465 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003466 }
Willy Tarreau23677902007-05-08 23:50:35 +02003467 else if (!strcmp(args[1], "smtpchk")) {
3468 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003469 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003470 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003471 curproxy->options2 &= ~PR_O2_CHK_ANY;
3472 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003473
3474 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3475 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3476 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3477 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3478 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3479 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3480 curproxy->check_req = (char *)malloc(reqlen);
3481 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3482 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3483 } else {
3484 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3485 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3486 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3487 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3488 }
3489 }
3490 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003491 else if (!strcmp(args[1], "lb-agent-chk")) {
3492 /* use dynmaic health check */
3493 free(curproxy->check_req);
3494 curproxy->check_req = NULL;
3495 curproxy->options2 &= ~PR_O2_CHK_ANY;
3496 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3497 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003498 else if (!strcmp(args[1], "pgsql-check")) {
3499 /* use PostgreSQL request to check servers' health */
3500 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3501 err_code |= ERR_WARN;
3502
3503 free(curproxy->check_req);
3504 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003505 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003506 curproxy->options2 |= PR_O2_PGSQL_CHK;
3507
3508 if (*(args[2])) {
3509 int cur_arg = 2;
3510
3511 while (*(args[cur_arg])) {
3512 if (strcmp(args[cur_arg], "user") == 0) {
3513 char * packet;
3514 uint32_t packet_len;
3515 uint32_t pv;
3516
3517 /* suboption header - needs additional argument for it */
3518 if (*(args[cur_arg+1]) == 0) {
3519 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3520 file, linenum, args[0], args[1], args[cur_arg]);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
3523 }
3524
3525 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3526 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3527 pv = htonl(0x30000); /* protocol version 3.0 */
3528
3529 packet = (char*) calloc(1, packet_len);
3530
3531 memcpy(packet + 4, &pv, 4);
3532
3533 /* copy "user" */
3534 memcpy(packet + 8, "user", 4);
3535
3536 /* copy username */
3537 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3538
3539 free(curproxy->check_req);
3540 curproxy->check_req = packet;
3541 curproxy->check_len = packet_len;
3542
3543 packet_len = htonl(packet_len);
3544 memcpy(packet, &packet_len, 4);
3545 cur_arg += 2;
3546 } else {
3547 /* unknown suboption - catchall */
3548 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3549 file, linenum, args[0], args[1]);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
3552 }
3553 } /* end while loop */
3554 }
3555 }
3556
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003557 else if (!strcmp(args[1], "redis-check")) {
3558 /* use REDIS PING request to check servers' health */
3559 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3560 err_code |= ERR_WARN;
3561
3562 free(curproxy->check_req);
3563 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003564 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003565 curproxy->options2 |= PR_O2_REDIS_CHK;
3566
3567 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3568 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3569 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3570 }
3571
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003572 else if (!strcmp(args[1], "mysql-check")) {
3573 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003574 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3575 err_code |= ERR_WARN;
3576
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003577 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003578 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003579 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003580 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003581
3582 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3583 * const char mysql40_client_auth_pkt[] = {
3584 * "\x0e\x00\x00" // packet length
3585 * "\x01" // packet number
3586 * "\x00\x00" // client capabilities
3587 * "\x00\x00\x01" // max packet
3588 * "haproxy\x00" // username (null terminated string)
3589 * "\x00" // filler (always 0x00)
3590 * "\x01\x00\x00" // packet length
3591 * "\x00" // packet number
3592 * "\x01" // COM_QUIT command
3593 * };
3594 */
3595
3596 if (*(args[2])) {
3597 int cur_arg = 2;
3598
3599 while (*(args[cur_arg])) {
3600 if (strcmp(args[cur_arg], "user") == 0) {
3601 char *mysqluser;
3602 int packetlen, reqlen, userlen;
3603
3604 /* suboption header - needs additional argument for it */
3605 if (*(args[cur_arg+1]) == 0) {
3606 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3607 file, linenum, args[0], args[1], args[cur_arg]);
3608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
3610 }
3611 mysqluser = args[cur_arg + 1];
3612 userlen = strlen(mysqluser);
3613 packetlen = userlen + 7;
3614 reqlen = packetlen + 9;
3615
3616 free(curproxy->check_req);
3617 curproxy->check_req = (char *)calloc(1, reqlen);
3618 curproxy->check_len = reqlen;
3619
3620 snprintf(curproxy->check_req, 4, "%c%c%c",
3621 ((unsigned char) packetlen & 0xff),
3622 ((unsigned char) (packetlen >> 8) & 0xff),
3623 ((unsigned char) (packetlen >> 16) & 0xff));
3624
3625 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003626 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003627 curproxy->check_req[8] = 1;
3628 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3629 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3630 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
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 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003641 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003642 else if (!strcmp(args[1], "ldap-check")) {
3643 /* use LDAP request to check servers' health */
3644 free(curproxy->check_req);
3645 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003646 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003647 curproxy->options2 |= PR_O2_LDAP_CHK;
3648
3649 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3650 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3651 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3652 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003653 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003654 int cur_arg;
3655
3656 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3657 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003658 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003659
Willy Tarreau87cf5142011-08-19 22:57:24 +02003660 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003661
3662 free(curproxy->fwdfor_hdr_name);
3663 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3664 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3665
3666 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3667 cur_arg = 2;
3668 while (*(args[cur_arg])) {
3669 if (!strcmp(args[cur_arg], "except")) {
3670 /* suboption except - needs additional argument for it */
3671 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3672 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3673 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003676 }
3677 /* flush useless bits */
3678 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003679 cur_arg += 2;
3680 } else if (!strcmp(args[cur_arg], "header")) {
3681 /* suboption header - needs additional argument for it */
3682 if (*(args[cur_arg+1]) == 0) {
3683 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3684 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003687 }
3688 free(curproxy->fwdfor_hdr_name);
3689 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3690 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3691 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003692 } else if (!strcmp(args[cur_arg], "if-none")) {
3693 curproxy->options &= ~PR_O_FF_ALWAYS;
3694 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003695 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003696 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003697 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003698 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003701 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003702 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003703 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003704 else if (!strcmp(args[1], "originalto")) {
3705 int cur_arg;
3706
3707 /* insert x-original-to field, but not for the IP address listed as an except.
3708 * set default options (ie: bitfield, header name, etc)
3709 */
3710
3711 curproxy->options |= PR_O_ORGTO;
3712
3713 free(curproxy->orgto_hdr_name);
3714 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3715 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3716
Willy Tarreau87cf5142011-08-19 22:57:24 +02003717 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003718 cur_arg = 2;
3719 while (*(args[cur_arg])) {
3720 if (!strcmp(args[cur_arg], "except")) {
3721 /* suboption except - needs additional argument for it */
3722 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3723 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3724 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003727 }
3728 /* flush useless bits */
3729 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3730 cur_arg += 2;
3731 } else if (!strcmp(args[cur_arg], "header")) {
3732 /* suboption header - needs additional argument for it */
3733 if (*(args[cur_arg+1]) == 0) {
3734 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3735 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003738 }
3739 free(curproxy->orgto_hdr_name);
3740 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3741 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3742 cur_arg += 2;
3743 } else {
3744 /* unknown suboption - catchall */
3745 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3746 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003749 }
3750 } /* end while loop */
3751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 else {
3753 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 }
Willy Tarreau93893792009-07-23 13:19:11 +02003757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003758 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003759 else if (!strcmp(args[0], "default_backend")) {
3760 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003762
3763 if (*(args[1]) == 0) {
3764 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003767 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003768 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003769 curproxy->defbe.name = strdup(args[1]);
3770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003772 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003774
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003775 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3776 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 /* enable reconnections to dispatch */
3779 curproxy->options |= PR_O_REDISP;
3780 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003781 else if (!strcmp(args[0], "http-check")) {
3782 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003784
3785 if (strcmp(args[1], "disable-on-404") == 0) {
3786 /* enable a graceful server shutdown on an HTTP 404 response */
3787 curproxy->options |= PR_O_DISABLE404;
3788 }
Willy Tarreauef781042010-01-27 11:53:01 +01003789 else if (strcmp(args[1], "send-state") == 0) {
3790 /* enable emission of the apparent state of a server in HTTP checks */
3791 curproxy->options2 |= PR_O2_CHK_SNDST;
3792 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003793 else if (strcmp(args[1], "expect") == 0) {
3794 const char *ptr_arg;
3795 int cur_arg;
3796
3797 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3798 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
3801 }
3802
3803 cur_arg = 2;
3804 /* consider exclamation marks, sole or at the beginning of a word */
3805 while (*(ptr_arg = args[cur_arg])) {
3806 while (*ptr_arg == '!') {
3807 curproxy->options2 ^= PR_O2_EXP_INV;
3808 ptr_arg++;
3809 }
3810 if (*ptr_arg)
3811 break;
3812 cur_arg++;
3813 }
3814 /* now ptr_arg points to the beginning of a word past any possible
3815 * exclamation mark, and cur_arg is the argument which holds this word.
3816 */
3817 if (strcmp(ptr_arg, "status") == 0) {
3818 if (!*(args[cur_arg + 1])) {
3819 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3820 file, linenum, args[0], args[1], ptr_arg);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003825 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003826 curproxy->expect_str = strdup(args[cur_arg + 1]);
3827 }
3828 else if (strcmp(ptr_arg, "string") == 0) {
3829 if (!*(args[cur_arg + 1])) {
3830 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3831 file, linenum, args[0], args[1], ptr_arg);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003836 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003837 curproxy->expect_str = strdup(args[cur_arg + 1]);
3838 }
3839 else if (strcmp(ptr_arg, "rstatus") == 0) {
3840 if (!*(args[cur_arg + 1])) {
3841 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3842 file, linenum, args[0], args[1], ptr_arg);
3843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
3845 }
3846 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003847 free(curproxy->expect_str);
3848 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3849 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003850 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3851 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3852 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3853 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
3856 }
3857 }
3858 else if (strcmp(ptr_arg, "rstring") == 0) {
3859 if (!*(args[cur_arg + 1])) {
3860 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3861 file, linenum, args[0], args[1], ptr_arg);
3862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
3864 }
3865 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003866 free(curproxy->expect_str);
3867 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3868 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003869 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3870 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3871 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3872 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
3875 }
3876 }
3877 else {
3878 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3879 file, linenum, args[0], args[1], ptr_arg);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003884 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003885 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 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003888 }
3889 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003890 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003891 if (curproxy == &defproxy) {
3892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003895 }
3896
Willy Tarreaub80c2302007-11-30 20:51:32 +01003897 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003899
3900 if (strcmp(args[1], "fail") == 0) {
3901 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003902 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003903 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3904 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003907 }
3908
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003909 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3910 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3911 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003914 }
3915 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3916 }
3917 else {
3918 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003921 }
3922 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923#ifdef TPROXY
3924 else if (!strcmp(args[0], "transparent")) {
3925 /* enable transparent proxy connections */
3926 curproxy->options |= PR_O_TRANSP;
3927 }
3928#endif
3929 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003930 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003932
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 if (*(args[1]) == 0) {
3934 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003937 }
3938 curproxy->maxconn = atol(args[1]);
3939 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003940 else if (!strcmp(args[0], "backlog")) { /* backlog */
3941 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003942 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003943
3944 if (*(args[1]) == 0) {
3945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003948 }
3949 curproxy->backlog = atol(args[1]);
3950 }
Willy Tarreau86034312006-12-29 00:10:33 +01003951 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003952 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003954
Willy Tarreau86034312006-12-29 00:10:33 +01003955 if (*(args[1]) == 0) {
3956 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003959 }
3960 curproxy->fullconn = atol(args[1]);
3961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3963 if (*(args[1]) == 0) {
3964 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003968 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3969 if (err) {
3970 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3971 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003974 }
3975 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 }
3977 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003978 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003979 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003980 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003981
Willy Tarreaubaaee002006-06-26 02:48:02 +02003982 if (curproxy == &defproxy) {
3983 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003987 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003989
Willy Tarreau902636f2013-03-10 19:44:48 +01003990 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003991 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01003992 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003993 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003994 goto out;
3995 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003996
3997 proto = protocol_by_family(sk->ss_family);
3998 if (!proto || !proto->connect) {
3999 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4000 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
4003 }
4004
4005 if (port1 != port2) {
4006 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4007 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004011
4012 if (!port1) {
4013 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4014 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004018
Willy Tarreaud5191e72010-02-09 20:50:45 +01004019 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004020 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 }
4022 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004023 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004024 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004025
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004026 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4027 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004032 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4033 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4034 err_code |= ERR_WARN;
4035
4036 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4037 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4038 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4039 }
4040 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4041 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4042 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4043 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004044 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4045 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4046 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4047 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004048 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004049 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
4052 }
4053 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004054 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004055 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004056 short realport = 0;
4057 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004059 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004064 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004065 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004066
4067 if (!*args[2]) {
4068 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4069 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004070 err_code |= ERR_ALERT | ERR_FATAL;
4071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004072 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004073
4074 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004075 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004076 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4077 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004080 }
4081
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004082 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004083 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004084 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004085 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004086
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004087 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4088 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4089 err_code |= ERR_ALERT | ERR_ABORT;
4090 goto out;
4091 }
4092
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004093 /* the servers are linked backwards first */
4094 newsrv->next = curproxy->srv;
4095 curproxy->srv = newsrv;
4096 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004097 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004098 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004100 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004101 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004102 LIST_INIT(&newsrv->pendconns);
4103 do_check = 0;
4104 newsrv->state = SRV_RUNNING; /* early server setup */
4105 newsrv->last_change = now.tv_sec;
4106 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004107
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004108 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004109 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004110 * - IP: => port=+0, relative
4111 * - IP:N => port=N, absolute
4112 * - IP:+N => port=+N, relative
4113 * - IP:-N => port=-N, relative
4114 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004115 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004116 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004117 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004118 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004119 goto out;
4120 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004121
4122 proto = protocol_by_family(sk->ss_family);
4123 if (!proto || !proto->connect) {
4124 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4125 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004129
4130 if (!port1 || !port2) {
4131 /* no port specified, +offset, -offset */
4132 newsrv->state |= SRV_MAPPORTS;
4133 }
4134 else if (port1 != port2) {
4135 /* port range */
4136 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4137 file, linenum, args[0], args[1], args[2]);
4138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
4140 }
4141 else {
4142 /* used by checks */
4143 realport = port1;
4144 }
4145
Willy Tarreaud5191e72010-02-09 20:50:45 +01004146 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004147 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4148 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004149
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004150 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004151 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4152 file, linenum, newsrv->addr.ss_family, args[2]);
4153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
4155 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004156
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004157 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004158 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004159 newsrv->inter = curproxy->defsrv.inter;
4160 newsrv->fastinter = curproxy->defsrv.fastinter;
4161 newsrv->downinter = curproxy->defsrv.downinter;
4162 newsrv->rise = curproxy->defsrv.rise;
4163 newsrv->fall = curproxy->defsrv.fall;
4164 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4165 newsrv->minconn = curproxy->defsrv.minconn;
4166 newsrv->maxconn = curproxy->defsrv.maxconn;
4167 newsrv->slowstart = curproxy->defsrv.slowstart;
4168 newsrv->onerror = curproxy->defsrv.onerror;
4169 newsrv->consecutive_errors_limit
4170 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004171#ifdef OPENSSL
4172 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4173#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004174 newsrv->uweight = newsrv->iweight
4175 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004177 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004179 cur_arg = 3;
4180 } else {
4181 newsrv = &curproxy->defsrv;
4182 cur_arg = 1;
4183 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004184
Willy Tarreaubaaee002006-06-26 02:48:02 +02004185 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004186 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 newsrv->cookie = strdup(args[cur_arg + 1]);
4188 newsrv->cklen = strlen(args[cur_arg + 1]);
4189 cur_arg += 2;
4190 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004191 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004192 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4193 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4194 cur_arg += 2;
4195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004197 if (!*args[cur_arg + 1]) {
4198 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4199 file, linenum, args[cur_arg]);
4200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
4202 }
4203
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004205 if (newsrv->rise <= 0) {
4206 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4207 file, linenum, args[cur_arg]);
4208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
4210 }
4211
Willy Tarreau96839092010-03-29 10:02:24 +02004212 if (newsrv->health)
4213 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004214 cur_arg += 2;
4215 }
4216 else if (!strcmp(args[cur_arg], "fall")) {
4217 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004218
4219 if (!*args[cur_arg + 1]) {
4220 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4221 file, linenum, args[cur_arg]);
4222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224 }
4225
4226 if (newsrv->fall <= 0) {
4227 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4228 file, linenum, args[cur_arg]);
4229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
4231 }
4232
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 cur_arg += 2;
4234 }
4235 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004236 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4237 if (err) {
4238 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4239 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004242 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004243 if (val <= 0) {
4244 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4245 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004248 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004249 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 cur_arg += 2;
4251 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004252 else if (!strcmp(args[cur_arg], "fastinter")) {
4253 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4254 if (err) {
4255 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4256 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004259 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004260 if (val <= 0) {
4261 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4262 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004265 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004266 newsrv->fastinter = val;
4267 cur_arg += 2;
4268 }
4269 else if (!strcmp(args[cur_arg], "downinter")) {
4270 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4271 if (err) {
4272 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4273 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004276 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004277 if (val <= 0) {
4278 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4279 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004282 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004283 newsrv->downinter = val;
4284 cur_arg += 2;
4285 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004286 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004287 struct sockaddr_storage *sk;
4288 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004289 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004290
Willy Tarreau902636f2013-03-10 19:44:48 +01004291 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004292 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004293 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004294 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004295 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004296 goto out;
4297 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004298
4299 proto = protocol_by_family(sk->ss_family);
4300 if (!proto || !proto->connect) {
4301 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004302 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
4305 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004306
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004307 if (port1 != port2) {
4308 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4309 file, linenum, args[cur_arg], args[cur_arg + 1]);
4310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
4312 }
4313
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004314 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004315 cur_arg += 2;
4316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004317 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004318 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004319 cur_arg += 2;
4320 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004321 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004322 newsrv->state |= SRV_BACKUP;
4323 cur_arg ++;
4324 }
Simon Hormanfa461682011-06-25 09:39:49 +09004325 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4326 newsrv->state |= SRV_NON_STICK;
4327 cur_arg ++;
4328 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004329 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4330 newsrv->state |= SRV_SEND_PROXY;
4331 cur_arg ++;
4332 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004333 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4334 newsrv->check.send_proxy = 1;
4335 cur_arg ++;
4336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004337 else if (!strcmp(args[cur_arg], "weight")) {
4338 int w;
4339 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004340 if (w < 0 || w > 256) {
4341 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004346 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004347 cur_arg += 2;
4348 }
4349 else if (!strcmp(args[cur_arg], "minconn")) {
4350 newsrv->minconn = atol(args[cur_arg + 1]);
4351 cur_arg += 2;
4352 }
4353 else if (!strcmp(args[cur_arg], "maxconn")) {
4354 newsrv->maxconn = atol(args[cur_arg + 1]);
4355 cur_arg += 2;
4356 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004357 else if (!strcmp(args[cur_arg], "maxqueue")) {
4358 newsrv->maxqueue = atol(args[cur_arg + 1]);
4359 cur_arg += 2;
4360 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004361 else if (!strcmp(args[cur_arg], "slowstart")) {
4362 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004363 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004364 if (err) {
4365 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4366 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004369 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004370 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004371 cur_arg += 2;
4372 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004373 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004374
4375 if (!*args[cur_arg + 1]) {
4376 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4377 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004380 }
4381
4382 newsrv->trackit = strdup(args[cur_arg + 1]);
4383
4384 cur_arg += 2;
4385 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004386 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 global.maxsock++;
4388 do_check = 1;
4389 cur_arg += 1;
4390 }
Willy Tarreau96839092010-03-29 10:02:24 +02004391 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4392 newsrv->state |= SRV_MAINTAIN;
4393 newsrv->state &= ~SRV_RUNNING;
4394 newsrv->health = 0;
4395 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004396 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004397 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004398 if (!strcmp(args[cur_arg + 1], "none"))
4399 newsrv->observe = HANA_OBS_NONE;
4400 else if (!strcmp(args[cur_arg + 1], "layer4"))
4401 newsrv->observe = HANA_OBS_LAYER4;
4402 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4403 if (curproxy->mode != PR_MODE_HTTP) {
4404 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4405 file, linenum, args[cur_arg + 1]);
4406 err_code |= ERR_ALERT;
4407 }
4408 newsrv->observe = HANA_OBS_LAYER7;
4409 }
4410 else {
4411 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004412 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004413 file, linenum, args[cur_arg], args[cur_arg + 1]);
4414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
4416 }
4417
4418 cur_arg += 2;
4419 }
4420 else if (!strcmp(args[cur_arg], "on-error")) {
4421 if (!strcmp(args[cur_arg + 1], "fastinter"))
4422 newsrv->onerror = HANA_ONERR_FASTINTER;
4423 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4424 newsrv->onerror = HANA_ONERR_FAILCHK;
4425 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4426 newsrv->onerror = HANA_ONERR_SUDDTH;
4427 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4428 newsrv->onerror = HANA_ONERR_MARKDWN;
4429 else {
4430 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004431 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004432 file, linenum, args[cur_arg], args[cur_arg + 1]);
4433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
4435 }
4436
4437 cur_arg += 2;
4438 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004439 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4440 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4441 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4442 else {
4443 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4444 file, linenum, args[cur_arg], args[cur_arg + 1]);
4445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
4447 }
4448
4449 cur_arg += 2;
4450 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004451 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4452 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4453 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4454 else {
4455 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4456 file, linenum, args[cur_arg], args[cur_arg + 1]);
4457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
4459 }
4460
4461 cur_arg += 2;
4462 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004463 else if (!strcmp(args[cur_arg], "error-limit")) {
4464 if (!*args[cur_arg + 1]) {
4465 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4466 file, linenum, args[cur_arg]);
4467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
4469 }
4470
4471 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4472
4473 if (newsrv->consecutive_errors_limit <= 0) {
4474 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4475 file, linenum, args[cur_arg]);
4476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
4478 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004479 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004480 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004481 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004482 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004483 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004484 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004485
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004487 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4488 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004489 err_code |= ERR_ALERT | ERR_FATAL;
4490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004492
Willy Tarreauef9a3602012-12-08 22:29:20 +01004493 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004494 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004495 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004496 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004497 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004498 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004499 goto out;
4500 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004501
4502 proto = protocol_by_family(sk->ss_family);
4503 if (!proto || !proto->connect) {
4504 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4505 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
4508 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004509
Willy Tarreauef9a3602012-12-08 22:29:20 +01004510 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004511
4512 if (port_low != port_high) {
4513 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004514
4515 if (!port_low || !port_high) {
4516 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4517 file, linenum, args[cur_arg], args[cur_arg + 1]);
4518 err_code |= ERR_ALERT | ERR_FATAL;
4519 goto out;
4520 }
4521
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004522 if (port_low <= 0 || port_low > 65535 ||
4523 port_high <= 0 || port_high > 65535 ||
4524 port_low > port_high) {
4525 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4526 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004529 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004530 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4531 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4532 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004533 }
4534
Willy Tarreaubaaee002006-06-26 02:48:02 +02004535 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004536 while (*(args[cur_arg])) {
4537 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004538#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4539#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004540 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004541 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4542 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004545 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004546#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004547 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004548 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004549 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004550 err_code |= ERR_ALERT | ERR_FATAL;
4551 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004552 }
4553 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004554 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4555 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004556 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004557 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4558 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004559 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4560 char *name, *end;
4561
4562 name = args[cur_arg+1] + 7;
4563 while (isspace(*name))
4564 name++;
4565
4566 end = name;
4567 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4568 end++;
4569
Willy Tarreauef9a3602012-12-08 22:29:20 +01004570 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4571 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4572 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4573 newsrv->conn_src.bind_hdr_len = end - name;
4574 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4575 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4576 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004577
4578 /* now look for an occurrence number */
4579 while (isspace(*end))
4580 end++;
4581 if (*end == ',') {
4582 end++;
4583 name = end;
4584 if (*end == '-')
4585 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004586 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004587 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004588 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004589 }
4590
Willy Tarreauef9a3602012-12-08 22:29:20 +01004591 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004592 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4593 " occurrences values smaller than %d.\n",
4594 file, linenum, MAX_HDR_HISTORY);
4595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
4597 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004598 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004599 struct sockaddr_storage *sk;
4600 int port1, port2;
4601
Willy Tarreau902636f2013-03-10 19:44:48 +01004602 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004603 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004604 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004605 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004606 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004607 goto out;
4608 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004609
4610 proto = protocol_by_family(sk->ss_family);
4611 if (!proto || !proto->connect) {
4612 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4613 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
4616 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004617
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004618 if (port1 != port2) {
4619 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4620 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
4623 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004624 newsrv->conn_src.tproxy_addr = *sk;
4625 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004626 }
4627 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004628#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004629 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004630#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004631 cur_arg += 2;
4632 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004633#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004634 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004635 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004638#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4639 } /* "usesrc" */
4640
4641 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4642#ifdef SO_BINDTODEVICE
4643 if (!*args[cur_arg + 1]) {
4644 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4645 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004648 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004649 free(newsrv->conn_src.iface_name);
4650 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4651 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004652 global.last_checks |= LSTCHK_NETADM;
4653#else
4654 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4655 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004656 err_code |= ERR_ALERT | ERR_FATAL;
4657 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004658#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004659 cur_arg += 2;
4660 continue;
4661 }
4662 /* this keyword in not an option of "source" */
4663 break;
4664 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004666 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004667 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4668 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004673 static int srv_dumped;
4674 struct srv_kw *kw;
4675 char *err;
4676
4677 kw = srv_find_kw(args[cur_arg]);
4678 if (kw) {
4679 char *err = NULL;
4680 int code;
4681
4682 if (!kw->parse) {
4683 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4684 file, linenum, args[0], args[1], args[cur_arg]);
4685 cur_arg += 1 + kw->skip ;
4686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
4688 }
4689
4690 if (defsrv && !kw->default_ok) {
4691 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4692 file, linenum, args[0], args[1], args[cur_arg]);
4693 cur_arg += 1 + kw->skip ;
4694 err_code |= ERR_ALERT;
4695 continue;
4696 }
4697
4698 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4699 err_code |= code;
4700
4701 if (code) {
4702 if (err && *err) {
4703 indent_msg(&err, 2);
4704 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4705 }
4706 else
4707 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4708 file, linenum, args[0], args[1], args[cur_arg]);
4709 if (code & ERR_FATAL) {
4710 free(err);
4711 cur_arg += 1 + kw->skip;
4712 goto out;
4713 }
4714 }
4715 free(err);
4716 cur_arg += 1 + kw->skip;
4717 continue;
4718 }
4719
4720 err = NULL;
4721 if (!srv_dumped) {
4722 srv_dump_kws(&err);
4723 indent_msg(&err, 4);
4724 srv_dumped = 1;
4725 }
4726
4727 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4728 file, linenum, args[0], args[1], args[cur_arg],
4729 err ? " Registered keywords :" : "", err ? err : "");
4730 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004731
Willy Tarreau93893792009-07-23 13:19:11 +02004732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004734 }
4735 }
4736
4737 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004738 if (newsrv->trackit) {
4739 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4740 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004743 }
4744
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004745 /* If neither a port nor an addr was specified and no check transport
4746 * layer is forced, then the transport layer used by the checks is the
4747 * same as for the production traffic. Otherwise we use raw_sock by
4748 * default, unless one is specified.
4749 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004750 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004751#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004752 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004753#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004754 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4755 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004756 /* try to get the port from check.addr if check.port not set */
4757 if (!newsrv->check.port)
4758 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004759
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004760 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004761 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004762
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004763 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004764 /* not yet valid, because no port was set on
4765 * the server either. We'll check if we have
4766 * a known port on the first listener.
4767 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004768 struct listener *l;
4769
4770 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004771 newsrv->check.port = get_host_port(&l->addr);
4772 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004773 break;
4774 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004775 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004776 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4778 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004779 err_code |= ERR_ALERT | ERR_FATAL;
4780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004782
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004783 /* Allocate buffer for check requests... */
4784 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004785 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4786 err_code |= ERR_ALERT | ERR_ABORT;
4787 goto out;
4788 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004789 newsrv->check.bi->size = global.tune.chksize;
4790
4791 /* Allocate buffer for check responses... */
4792 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4793 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4794 err_code |= ERR_ALERT | ERR_ABORT;
4795 goto out;
4796 }
4797 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004798
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004799 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004800 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004801 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4802 err_code |= ERR_ALERT | ERR_ABORT;
4803 goto out;
4804 }
4805
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004806 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4807 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004808 newsrv->state |= SRV_CHECKED;
4809 }
4810
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004811 if (!defsrv) {
4812 if (newsrv->state & SRV_BACKUP)
4813 curproxy->srv_bck++;
4814 else
4815 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004816
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004817 newsrv->prev_state = newsrv->state;
4818 }
William Lallemanda73203e2012-03-12 12:48:57 +01004819 }
4820
4821 else if (strcmp(args[0], "unique-id-format") == 0) {
4822 if (!*(args[1])) {
4823 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4824 err_code |= ERR_ALERT | ERR_FATAL;
4825 goto out;
4826 }
William Lallemand3203ff42012-11-11 17:30:56 +01004827 if (*(args[2])) {
4828 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4829 err_code |= ERR_ALERT | ERR_FATAL;
4830 goto out;
4831 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004832 free(curproxy->uniqueid_format_string);
4833 curproxy->uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004834
4835 /* get a chance to improve log-format error reporting by
4836 * reporting the correct line-number when possible.
4837 */
4838 if (curproxy != &defproxy) {
4839 curproxy->conf.args.ctx = ARGC_UIF;
4840 if (curproxy->uniqueid_format_string)
4841 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
4842 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
4843 free(curproxy->uniqueid_format_string);
4844 curproxy->uniqueid_format_string = NULL;
4845 }
William Lallemand723b73a2012-02-08 16:37:49 +01004846 }
William Lallemanda73203e2012-03-12 12:48:57 +01004847
4848 else if (strcmp(args[0], "unique-id-header") == 0) {
4849 if (!*(args[1])) {
4850 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
4853 }
4854 free(curproxy->header_unique_id);
4855 curproxy->header_unique_id = strdup(args[1]);
4856 }
4857
William Lallemand723b73a2012-02-08 16:37:49 +01004858 else if (strcmp(args[0], "log-format") == 0) {
4859 if (!*(args[1])) {
4860 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
4863 }
William Lallemand3203ff42012-11-11 17:30:56 +01004864 if (*(args[2])) {
4865 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
4868 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004869
4870 if (curproxy->logformat_string != default_http_log_format &&
4871 curproxy->logformat_string != default_tcp_log_format &&
4872 curproxy->logformat_string != clf_http_log_format)
4873 free(curproxy->logformat_string);
4874 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004875
4876 /* get a chance to improve log-format error reporting by
4877 * reporting the correct line-number when possible.
4878 */
4879 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4880 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4881 file, linenum, curproxy->id);
4882 err_code |= ERR_WARN;
4883 }
4884 else if (curproxy->cap & PR_CAP_FE) {
4885 curproxy->conf.args.ctx = ARGC_LOG;
4886 if (curproxy->logformat_string)
4887 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
4888 SMP_VAL_FE_LOG_END);
4889 free(curproxy->logformat_string);
4890 curproxy->logformat_string = NULL;
4891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004892 }
William Lallemand723b73a2012-02-08 16:37:49 +01004893
William Lallemand0f99e342011-10-12 17:50:54 +02004894 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4895 /* delete previous herited or defined syslog servers */
4896 struct logsrv *back;
4897
4898 if (*(args[1]) != 0) {
4899 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
4902 }
4903
William Lallemand723b73a2012-02-08 16:37:49 +01004904 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4905 LIST_DEL(&tmplogsrv->list);
4906 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004907 }
4908 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004910 struct logsrv *logsrv;
4911
Willy Tarreaubaaee002006-06-26 02:48:02 +02004912 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004913 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004914 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004915 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004916 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004917 LIST_INIT(&node->list);
4918 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4919 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
4921 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004922 struct sockaddr_storage *sk;
4923 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004924
4925 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926
William Lallemand0f99e342011-10-12 17:50:54 +02004927 logsrv->facility = get_log_facility(args[2]);
4928 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004930 err_code |= ERR_ALERT | ERR_FATAL;
4931 goto out;
4932
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933 }
4934
William Lallemand0f99e342011-10-12 17:50:54 +02004935 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004937 logsrv->level = get_log_level(args[3]);
4938 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
4942
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 }
4944 }
4945
William Lallemand0f99e342011-10-12 17:50:54 +02004946 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004947 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004948 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004949 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004950 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004951 err_code |= ERR_ALERT | ERR_FATAL;
4952 goto out;
4953
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004954 }
4955 }
4956
Willy Tarreau902636f2013-03-10 19:44:48 +01004957 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004958 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004959 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004960 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004961 goto out;
4962 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004963
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004964 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004965
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004966 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004967 if (port1 != port2) {
4968 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4969 file, linenum, args[0], args[1]);
4970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
4972 }
4973
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004974 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004975 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 }
William Lallemand0f99e342011-10-12 17:50:54 +02004977
4978 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
4980 else {
4981 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4982 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004983 err_code |= ERR_ALERT | ERR_FATAL;
4984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 }
4986 }
4987 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004988 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004989 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004990 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004991 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004992
Willy Tarreau977b8e42006-12-29 14:19:17 +01004993 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004994 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004995
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004997 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4998 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005002
5003 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005004 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5005 free(curproxy->conn_src.iface_name);
5006 curproxy->conn_src.iface_name = NULL;
5007 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005008
Willy Tarreau902636f2013-03-10 19:44:48 +01005009 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005010 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005011 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005012 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005013 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005014 goto out;
5015 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005016
5017 proto = protocol_by_family(sk->ss_family);
5018 if (!proto || !proto->connect) {
5019 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005020 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005024
5025 if (port1 != port2) {
5026 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5027 file, linenum, args[0], args[1]);
5028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
5030 }
5031
Willy Tarreauef9a3602012-12-08 22:29:20 +01005032 curproxy->conn_src.source_addr = *sk;
5033 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005034
5035 cur_arg = 2;
5036 while (*(args[cur_arg])) {
5037 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005038#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
5039#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005040 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005041 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5042 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005045 }
5046#endif
5047 if (!*args[cur_arg + 1]) {
5048 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5049 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005050 err_code |= ERR_ALERT | ERR_FATAL;
5051 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005052 }
5053
5054 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005055 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5056 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005057 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005058 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5059 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005060 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5061 char *name, *end;
5062
5063 name = args[cur_arg+1] + 7;
5064 while (isspace(*name))
5065 name++;
5066
5067 end = name;
5068 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5069 end++;
5070
Willy Tarreauef9a3602012-12-08 22:29:20 +01005071 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5072 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5073 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5074 curproxy->conn_src.bind_hdr_len = end - name;
5075 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5076 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5077 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005078
5079 /* now look for an occurrence number */
5080 while (isspace(*end))
5081 end++;
5082 if (*end == ',') {
5083 end++;
5084 name = end;
5085 if (*end == '-')
5086 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005087 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005088 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005089 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005090 }
5091
Willy Tarreauef9a3602012-12-08 22:29:20 +01005092 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005093 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5094 " occurrences values smaller than %d.\n",
5095 file, linenum, MAX_HDR_HISTORY);
5096 err_code |= ERR_ALERT | ERR_FATAL;
5097 goto out;
5098 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005099 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005100 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005101
Willy Tarreau902636f2013-03-10 19:44:48 +01005102 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005103 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005104 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005105 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005106 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005107 goto out;
5108 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005109
5110 proto = protocol_by_family(sk->ss_family);
5111 if (!proto || !proto->connect) {
5112 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5113 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
5116 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005117
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005118 if (port1 != port2) {
5119 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5120 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
5123 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005124 curproxy->conn_src.tproxy_addr = *sk;
5125 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005126 }
5127 global.last_checks |= LSTCHK_NETADM;
5128#if !defined(CONFIG_HAP_LINUX_TPROXY)
5129 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005130#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005131#else /* no TPROXY support */
5132 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005133 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005136#endif
5137 cur_arg += 2;
5138 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005139 }
5140
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005141 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5142#ifdef SO_BINDTODEVICE
5143 if (!*args[cur_arg + 1]) {
5144 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5145 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005148 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005149 free(curproxy->conn_src.iface_name);
5150 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5151 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005152 global.last_checks |= LSTCHK_NETADM;
5153#else
5154 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5155 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_ALERT | ERR_FATAL;
5157 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005158#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005159 cur_arg += 2;
5160 continue;
5161 }
5162 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005163 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005168 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5169 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5170 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005175 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5177 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005181
5182 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005183 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005184 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 }
5188 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005190 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005191 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005194 }
5195 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005196 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005197 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005198 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 }
5202 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005203 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005204 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005205 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005206 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005208 }
5209 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005210 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005211 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005212 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005213 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005215 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005216 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005217 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005218 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005219 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005220 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005221 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005222 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005223 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005224 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005225 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005226 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005227 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005228 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005229 }
5230 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005231 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005232 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005233 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005234 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005235 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005238 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005239 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5240 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005243 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005244
5245 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005246 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005247 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005248 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 }
5251 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005253 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005254 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005255 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 }
5258 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005259 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005260 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005261 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005262 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 }
5265 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005267 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005268 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005269 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 }
5272 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005273 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005274 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005275 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005276 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005278 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005279 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005280 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005281 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005282 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005283 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005284 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005287 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005288
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 if (curproxy == &defproxy) {
5290 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005294 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005295 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297 if (*(args[1]) == 0) {
5298 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005302
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005303 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005304 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5305 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5306 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
5309 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005310 err_code |= warnif_cond_conflicts(cond,
5311 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5312 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005313 }
5314 else if (*args[2]) {
5315 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5316 file, linenum, args[0], args[2]);
5317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
5319 }
5320
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005321 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005322 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005323 wl->s = strdup(args[1]);
5324 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005325 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 }
5327 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005328 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005331 err_code |= ERR_ALERT | ERR_FATAL;
5332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005334
Willy Tarreauade5ec42010-01-28 19:33:49 +01005335 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005336 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005337 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005338 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 }
5341 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005342 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005343 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005344 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005345 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 }
5348 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005349 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005350 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005351 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005352 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005354 }
5355 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005356 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005357 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5358 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005361 }
5362
Willy Tarreauade5ec42010-01-28 19:33:49 +01005363 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005364 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005365 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005366 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 }
5369 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005370 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005371 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005372 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005373 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005375 }
5376 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005377 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005378 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005379 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005380 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 }
5383 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005384 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005385
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 if (curproxy == &defproxy) {
5387 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005391 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005392 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 if (*(args[1]) == 0) {
5395 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 }
5399
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005400 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005401 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5402 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5403 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005407 err_code |= warnif_cond_conflicts(cond,
5408 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5409 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005410 }
5411 else if (*args[2]) {
5412 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5413 file, linenum, args[0], args[2]);
5414 err_code |= ERR_ALERT | ERR_FATAL;
5415 goto out;
5416 }
5417
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005418 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005419 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005420 wl->s = strdup(args[1]);
5421 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 }
5423 else if (!strcmp(args[0], "errorloc") ||
5424 !strcmp(args[0], "errorloc302") ||
5425 !strcmp(args[0], "errorloc303")) { /* error location */
5426 int errnum, errlen;
5427 char *err;
5428
Willy Tarreau977b8e42006-12-29 14:19:17 +01005429 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005430 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005431
Willy Tarreaubaaee002006-06-26 02:48:02 +02005432 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005433 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005436 }
5437
5438 errnum = atol(args[1]);
5439 if (!strcmp(args[0], "errorloc303")) {
5440 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5441 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5442 } else {
5443 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5444 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5445 }
5446
Willy Tarreau0f772532006-12-23 20:51:41 +01005447 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5448 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005449 chunk_destroy(&curproxy->errmsg[rc]);
5450 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005451 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005452 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005454
5455 if (rc >= HTTP_ERR_SIZE) {
5456 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5457 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005458 free(err);
5459 }
5460 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005461 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5462 int errnum, errlen, fd;
5463 char *err;
5464 struct stat stat;
5465
5466 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005467 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005468
5469 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005470 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005471 err_code |= ERR_ALERT | ERR_FATAL;
5472 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005473 }
5474
5475 fd = open(args[2], O_RDONLY);
5476 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5477 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5478 file, linenum, args[2], args[1]);
5479 if (fd >= 0)
5480 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005481 err_code |= ERR_ALERT | ERR_FATAL;
5482 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005483 }
5484
Willy Tarreau27a674e2009-08-17 07:23:33 +02005485 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005486 errlen = stat.st_size;
5487 } else {
5488 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005489 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005490 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005491 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005492 }
5493
5494 err = malloc(errlen); /* malloc() must succeed during parsing */
5495 errnum = read(fd, err, errlen);
5496 if (errnum != errlen) {
5497 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5498 file, linenum, args[2], args[1]);
5499 close(fd);
5500 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005501 err_code |= ERR_ALERT | ERR_FATAL;
5502 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005503 }
5504 close(fd);
5505
5506 errnum = atol(args[1]);
5507 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5508 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005509 chunk_destroy(&curproxy->errmsg[rc]);
5510 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005511 break;
5512 }
5513 }
5514
5515 if (rc >= HTTP_ERR_SIZE) {
5516 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5517 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005518 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005519 free(err);
5520 }
5521 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005522 else if (!strcmp(args[0], "compression")) {
5523 struct comp *comp;
5524 if (curproxy->comp == NULL) {
5525 comp = calloc(1, sizeof(struct comp));
5526 curproxy->comp = comp;
5527 } else {
5528 comp = curproxy->comp;
5529 }
5530
5531 if (!strcmp(args[1], "algo")) {
5532 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005533 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005534
William Lallemand82fe75c2012-10-23 10:25:10 +02005535 cur_arg = 2;
5536 if (!*args[cur_arg]) {
5537 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5538 file, linenum, args[0]);
5539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
5541 }
5542 while (*(args[cur_arg])) {
5543 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5544 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5545 file, linenum, args[0], args[cur_arg]);
5546 err_code |= ERR_ALERT | ERR_FATAL;
5547 goto out;
5548 }
William Lallemand552df672012-11-07 13:21:47 +01005549 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5550 curproxy->comp->algos->end(&ctx);
5551 } else {
5552 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5553 file, linenum, args[0], args[cur_arg]);
5554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
5556 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005557 cur_arg ++;
5558 continue;
5559 }
5560 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005561 else if (!strcmp(args[1], "offload")) {
5562 comp->offload = 1;
5563 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005564 else if (!strcmp(args[1], "type")) {
5565 int cur_arg;
5566 cur_arg = 2;
5567 if (!*args[cur_arg]) {
5568 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5569 file, linenum, args[0]);
5570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
5572 }
5573 while (*(args[cur_arg])) {
5574 comp_append_type(comp, args[cur_arg]);
5575 cur_arg ++;
5576 continue;
5577 }
5578 }
5579 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005580 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005581 file, linenum, args[0]);
5582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
5584 }
5585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005587 struct cfg_kw_list *kwl;
5588 int index;
5589
5590 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5591 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5592 if (kwl->kw[index].section != CFG_LISTEN)
5593 continue;
5594 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5595 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005596 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005597 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005598 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005601 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005602 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005603 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005604 err_code |= ERR_WARN;
5605 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005606 }
Willy Tarreau93893792009-07-23 13:19:11 +02005607 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005608 }
5609 }
5610 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005611
Willy Tarreau6daf3432008-01-22 16:44:08 +01005612 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 }
Willy Tarreau93893792009-07-23 13:19:11 +02005616 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005617 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005618 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619}
5620
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005621int
5622cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5623{
5624
5625 int err_code = 0;
5626 const char *err;
5627
5628 if (!strcmp(args[0], "userlist")) { /* new userlist */
5629 struct userlist *newul;
5630
5631 if (!*args[1]) {
5632 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5633 file, linenum, args[0]);
5634 err_code |= ERR_ALERT | ERR_FATAL;
5635 goto out;
5636 }
5637
5638 err = invalid_char(args[1]);
5639 if (err) {
5640 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5641 file, linenum, *err, args[0], args[1]);
5642 err_code |= ERR_ALERT | ERR_FATAL;
5643 goto out;
5644 }
5645
5646 for (newul = userlist; newul; newul = newul->next)
5647 if (!strcmp(newul->name, args[1])) {
5648 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5649 file, linenum, args[1]);
5650 err_code |= ERR_WARN;
5651 goto out;
5652 }
5653
5654 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5655 if (!newul) {
5656 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5657 err_code |= ERR_ALERT | ERR_ABORT;
5658 goto out;
5659 }
5660
5661 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5662 newul->name = strdup(args[1]);
5663
5664 if (!newul->groupusers | !newul->name) {
5665 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5666 err_code |= ERR_ALERT | ERR_ABORT;
5667 goto out;
5668 }
5669
5670 newul->next = userlist;
5671 userlist = newul;
5672
5673 } else if (!strcmp(args[0], "group")) { /* new group */
5674 int cur_arg, i;
5675 const char *err;
5676
5677 if (!*args[1]) {
5678 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5679 file, linenum, args[0]);
5680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
5682 }
5683
5684 err = invalid_char(args[1]);
5685 if (err) {
5686 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5687 file, linenum, *err, args[0], args[1]);
5688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
5690 }
5691
5692 for(i = 0; i < userlist->grpcnt; i++)
5693 if (!strcmp(userlist->groups[i], args[1])) {
5694 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5695 file, linenum, args[1], userlist->name);
5696 err_code |= ERR_ALERT;
5697 goto out;
5698 }
5699
5700 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5701 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5702 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
5705 }
5706
5707 cur_arg = 2;
5708
5709 while (*args[cur_arg]) {
5710 if (!strcmp(args[cur_arg], "users")) {
5711 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5712 cur_arg += 2;
5713 continue;
5714 } else {
5715 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5716 file, linenum, args[0]);
5717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
5719 }
5720 }
5721
5722 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5723 } else if (!strcmp(args[0], "user")) { /* new user */
5724 struct auth_users *newuser;
5725 int cur_arg;
5726
5727 if (!*args[1]) {
5728 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5729 file, linenum, args[0]);
5730 err_code |= ERR_ALERT | ERR_FATAL;
5731 goto out;
5732 }
5733
5734 for (newuser = userlist->users; newuser; newuser = newuser->next)
5735 if (!strcmp(newuser->user, args[1])) {
5736 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5737 file, linenum, args[1], userlist->name);
5738 err_code |= ERR_ALERT;
5739 goto out;
5740 }
5741
5742 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5743 if (!newuser) {
5744 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5745 err_code |= ERR_ALERT | ERR_ABORT;
5746 goto out;
5747 }
5748
5749 newuser->user = strdup(args[1]);
5750
5751 newuser->next = userlist->users;
5752 userlist->users = newuser;
5753
5754 cur_arg = 2;
5755
5756 while (*args[cur_arg]) {
5757 if (!strcmp(args[cur_arg], "password")) {
5758#ifndef CONFIG_HAP_CRYPT
5759 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5760 file, linenum);
5761 err_code |= ERR_ALERT;
5762#endif
5763 newuser->pass = strdup(args[cur_arg + 1]);
5764 cur_arg += 2;
5765 continue;
5766 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5767 newuser->pass = strdup(args[cur_arg + 1]);
5768 newuser->flags |= AU_O_INSECURE;
5769 cur_arg += 2;
5770 continue;
5771 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005772 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005773 cur_arg += 2;
5774 continue;
5775 } else {
5776 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5777 file, linenum, args[0]);
5778 err_code |= ERR_ALERT | ERR_FATAL;
5779 goto out;
5780 }
5781 }
5782 } else {
5783 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5784 err_code |= ERR_ALERT | ERR_FATAL;
5785 }
5786
5787out:
5788 return err_code;
5789}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005790
5791/*
5792 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005793 * Returns the error code, 0 if OK, or any combination of :
5794 * - ERR_ABORT: must abort ASAP
5795 * - ERR_FATAL: we can continue parsing but not start the service
5796 * - ERR_WARN: a warning has been emitted
5797 * - ERR_ALERT: an alert has been emitted
5798 * Only the two first ones can stop processing, the two others are just
5799 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005800 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005801int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005803 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005804 FILE *f;
5805 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005807 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809 if ((f=fopen(file,"r")) == NULL)
5810 return -1;
5811
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005812 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005813 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005814 char *end;
5815 char *args[MAX_LINE_ARGS + 1];
5816 char *line = thisline;
5817
Willy Tarreaubaaee002006-06-26 02:48:02 +02005818 linenum++;
5819
5820 end = line + strlen(line);
5821
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005822 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5823 /* Check if we reached the limit and the last char is not \n.
5824 * Watch out for the last line without the terminating '\n'!
5825 */
5826 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005827 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005828 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005829 }
5830
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005832 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 line++;
5834
5835 arg = 0;
5836 args[arg] = line;
5837
5838 while (*line && arg < MAX_LINE_ARGS) {
5839 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5840 * C equivalent value. Other combinations left unchanged (eg: \1).
5841 */
5842 if (*line == '\\') {
5843 int skip = 0;
5844 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5845 *line = line[1];
5846 skip = 1;
5847 }
5848 else if (line[1] == 'r') {
5849 *line = '\r';
5850 skip = 1;
5851 }
5852 else if (line[1] == 'n') {
5853 *line = '\n';
5854 skip = 1;
5855 }
5856 else if (line[1] == 't') {
5857 *line = '\t';
5858 skip = 1;
5859 }
5860 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005861 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005862 unsigned char hex1, hex2;
5863 hex1 = toupper(line[2]) - '0';
5864 hex2 = toupper(line[3]) - '0';
5865 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5866 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5867 *line = (hex1<<4) + hex2;
5868 skip = 3;
5869 }
5870 else {
5871 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005872 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 }
5874 }
5875 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005876 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877 end -= skip;
5878 }
5879 line++;
5880 }
5881 else if (*line == '#' || *line == '\n' || *line == '\r') {
5882 /* end of string, end of loop */
5883 *line = 0;
5884 break;
5885 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005886 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005887 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005888 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005889 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005890 line++;
5891 args[++arg] = line;
5892 }
5893 else {
5894 line++;
5895 }
5896 }
5897
5898 /* empty line */
5899 if (!**args)
5900 continue;
5901
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005902 if (*line) {
5903 /* we had to stop due to too many args.
5904 * Let's terminate the string, print the offending part then cut the
5905 * last arg.
5906 */
5907 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5908 line++;
5909 *line = '\0';
5910
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005911 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005912 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005913 err_code |= ERR_ALERT | ERR_FATAL;
5914 args[arg] = line;
5915 }
5916
Willy Tarreau540abe42007-05-02 20:50:16 +02005917 /* zero out remaining args and ensure that at least one entry
5918 * is zeroed out.
5919 */
5920 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005921 args[arg] = line;
5922 }
5923
Willy Tarreau3842f002009-06-14 11:39:52 +02005924 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005925 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005926 char *tmp;
5927
Willy Tarreau3842f002009-06-14 11:39:52 +02005928 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005929 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005930 for (arg=0; *args[arg+1]; arg++)
5931 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005932 *tmp = '\0'; // fix the next arg to \0
5933 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005934 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005935 else if (!strcmp(args[0], "default")) {
5936 kwm = KWM_DEF;
5937 for (arg=0; *args[arg+1]; arg++)
5938 args[arg] = args[arg+1]; // shift args after inversion
5939 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005940
William Lallemand0f99e342011-10-12 17:50:54 +02005941 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5942 strcmp(args[0], "log") != 0) {
5943 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005944 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005945 }
5946
Willy Tarreau977b8e42006-12-29 14:19:17 +01005947 if (!strcmp(args[0], "listen") ||
5948 !strcmp(args[0], "frontend") ||
5949 !strcmp(args[0], "backend") ||
5950 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005951 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005952 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005953 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005954 cursection = strdup(args[0]);
5955 }
5956 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005958 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005959 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005960 }
5961 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005962 confsect = CFG_USERLIST;
5963 free(cursection);
5964 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005965 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005966 else if (!strcmp(args[0], "peers")) {
5967 confsect = CFG_PEERS;
5968 free(cursection);
5969 cursection = strdup(args[0]);
5970 }
5971
Willy Tarreaubaaee002006-06-26 02:48:02 +02005972 /* else it's a section keyword */
5973
5974 switch (confsect) {
5975 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005976 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 break;
5978 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005979 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005981 case CFG_USERLIST:
5982 err_code |= cfg_parse_users(file, linenum, args, kwm);
5983 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005984 case CFG_PEERS:
5985 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5986 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005987 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005988 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005989 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005990 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005991
5992 if (err_code & ERR_ABORT)
5993 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005994 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005995 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005996 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005998 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005999}
6000
Willy Tarreaubb925012009-07-23 13:36:36 +02006001/*
6002 * Returns the error code, 0 if OK, or any combination of :
6003 * - ERR_ABORT: must abort ASAP
6004 * - ERR_FATAL: we can continue parsing but not start the service
6005 * - ERR_WARN: a warning has been emitted
6006 * - ERR_ALERT: an alert has been emitted
6007 * Only the two first ones can stop processing, the two others are just
6008 * indicators.
6009 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006010int check_config_validity()
6011{
6012 int cfgerr = 0;
6013 struct proxy *curproxy = NULL;
6014 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006015 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006016 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006017 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006018 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006020 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006021 /*
6022 * Now, check for the integrity of all that we have collected.
6023 */
6024
6025 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006026 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006027
Willy Tarreau193b8c62012-11-22 00:17:38 +01006028 if (!global.tune.max_http_hdr)
6029 global.tune.max_http_hdr = MAX_HTTP_HDR;
6030
6031 if (!global.tune.cookie_len)
6032 global.tune.cookie_len = CAPTURE_LEN;
6033
6034 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6035
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006036 /* first, we will invert the proxy list order */
6037 curproxy = NULL;
6038 while (proxy) {
6039 struct proxy *next;
6040
6041 next = proxy->next;
6042 proxy->next = curproxy;
6043 curproxy = proxy;
6044 if (!next)
6045 break;
6046 proxy = next;
6047 }
6048
Willy Tarreaubaaee002006-06-26 02:48:02 +02006049 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006050 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006051 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006052 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006053 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006054 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006055 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006056 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006057
Willy Tarreau050536d2012-10-04 08:47:34 +02006058 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006059 /* proxy ID not set, use automatic numbering with first
6060 * spare entry starting with next_pxid.
6061 */
6062 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6063 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6064 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006065 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006066 next_pxid++;
6067
Willy Tarreau55ea7572007-06-17 19:56:27 +02006068
Willy Tarreaubaaee002006-06-26 02:48:02 +02006069 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006070 /* ensure we don't keep listeners uselessly bound */
6071 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006072 curproxy = curproxy->next;
6073 continue;
6074 }
6075
Willy Tarreau16a21472012-11-19 12:39:59 +01006076 /* number of processes this proxy is bound to */
6077 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6078
Willy Tarreauff01a212009-03-15 13:46:16 +01006079 switch (curproxy->mode) {
6080 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006081 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006082 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006083 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6084 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006085 cfgerr++;
6086 }
6087
6088 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006089 Warning("config : servers will be ignored for %s '%s'.\n",
6090 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006091 break;
6092
6093 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006094 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006095 break;
6096
6097 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006098 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006099 break;
6100 }
6101
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006102 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006103 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006104 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006105 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6106 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006107 cfgerr++;
6108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006109#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006110 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006111 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6112 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006113 cfgerr++;
6114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006115#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006116 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006117 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6118 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006119 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006120 }
6121 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006122 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006123 /* If no LB algo is set in a backend, and we're not in
6124 * transparent mode, dispatch mode nor proxy mode, we
6125 * want to use balance roundrobin by default.
6126 */
6127 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6128 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006129 }
6130 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006131
Willy Tarreau1620ec32011-08-06 17:05:02 +02006132 if (curproxy->options & PR_O_DISPATCH)
6133 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6134 else if (curproxy->options & PR_O_HTTP_PROXY)
6135 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6136 else if (curproxy->options & PR_O_TRANSP)
6137 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006138
Willy Tarreau1620ec32011-08-06 17:05:02 +02006139 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6140 if (curproxy->options & PR_O_DISABLE404) {
6141 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6142 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6143 err_code |= ERR_WARN;
6144 curproxy->options &= ~PR_O_DISABLE404;
6145 }
6146 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6147 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6148 "send-state", proxy_type_str(curproxy), curproxy->id);
6149 err_code |= ERR_WARN;
6150 curproxy->options &= ~PR_O2_CHK_SNDST;
6151 }
Willy Tarreauef781042010-01-27 11:53:01 +01006152 }
6153
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006154 /* if a default backend was specified, let's find it */
6155 if (curproxy->defbe.name) {
6156 struct proxy *target;
6157
Alex Williams96532db2009-11-01 21:27:13 -05006158 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006159 if (!target) {
6160 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6161 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006162 cfgerr++;
6163 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006164 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6165 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006166 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006167 } else {
6168 free(curproxy->defbe.name);
6169 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006170 /* we force the backend to be present on at least all of
6171 * the frontend's processes.
6172 */
6173 target->bind_proc = curproxy->bind_proc ?
6174 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006175
6176 /* Emit a warning if this proxy also has some servers */
6177 if (curproxy->srv) {
6178 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6179 curproxy->id);
6180 err_code |= ERR_WARN;
6181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182 }
6183 }
6184
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006185 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006186 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6187 /* map jump target for ACT_SETBE in req_rep chain */
6188 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006189 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006190 struct proxy *target;
6191
Willy Tarreaua496b602006-12-17 23:15:24 +01006192 if (exp->action != ACT_SETBE)
6193 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006194
Alex Williams96532db2009-11-01 21:27:13 -05006195 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006196 if (!target) {
6197 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6198 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006199 cfgerr++;
6200 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006201 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6202 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006203 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006204 } else {
6205 free((void *)exp->replace);
6206 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006207 /* we force the backend to be present on at least all of
6208 * the frontend's processes.
6209 */
6210 target->bind_proc = curproxy->bind_proc ?
6211 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006212 }
6213 }
6214 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006215
6216 /* find the target proxy for 'use_backend' rules */
6217 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006218 struct proxy *target;
6219
Alex Williams96532db2009-11-01 21:27:13 -05006220 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006221
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006222 if (!target) {
6223 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6224 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006225 cfgerr++;
6226 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006227 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6228 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006229 cfgerr++;
6230 } else {
6231 free((void *)rule->be.name);
6232 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006233 /* we force the backend to be present on at least all of
6234 * the frontend's processes.
6235 */
6236 target->bind_proc = curproxy->bind_proc ?
6237 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006238 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006239 }
6240
6241 /* find the target proxy for 'use_backend' rules */
6242 list_for_each_entry(srule, &curproxy->server_rules, list) {
6243 struct server *target = findserver(curproxy, srule->srv.name);
6244
6245 if (!target) {
6246 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6247 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6248 cfgerr++;
6249 continue;
6250 }
6251 free((void *)srule->srv.name);
6252 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006253 }
6254
Emeric Brunb982a3d2010-01-04 15:45:53 +01006255 /* find the target table for 'stick' rules */
6256 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6257 struct proxy *target;
6258
Emeric Brun1d33b292010-01-04 15:47:17 +01006259 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6260 if (mrule->flags & STK_IS_STORE)
6261 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6262
Emeric Brunb982a3d2010-01-04 15:45:53 +01006263 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006264 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006265 else
6266 target = curproxy;
6267
6268 if (!target) {
6269 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6270 curproxy->id, mrule->table.name);
6271 cfgerr++;
6272 }
6273 else if (target->table.size == 0) {
6274 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6275 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6276 cfgerr++;
6277 }
Willy Tarreau12785782012-04-27 21:37:17 +02006278 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6279 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006280 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6281 cfgerr++;
6282 }
6283 else {
6284 free((void *)mrule->table.name);
6285 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006286 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006287 }
6288 }
6289
6290 /* find the target table for 'store response' rules */
6291 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6292 struct proxy *target;
6293
Emeric Brun1d33b292010-01-04 15:47:17 +01006294 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6295
Emeric Brunb982a3d2010-01-04 15:45:53 +01006296 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006297 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006298 else
6299 target = curproxy;
6300
6301 if (!target) {
6302 Alert("Proxy '%s': unable to find store table '%s'.\n",
6303 curproxy->id, mrule->table.name);
6304 cfgerr++;
6305 }
6306 else if (target->table.size == 0) {
6307 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6308 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6309 cfgerr++;
6310 }
Willy Tarreau12785782012-04-27 21:37:17 +02006311 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6312 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006313 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6314 cfgerr++;
6315 }
6316 else {
6317 free((void *)mrule->table.name);
6318 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006319 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006320 }
6321 }
6322
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006323 /* find the target table for 'tcp-request' layer 4 rules */
6324 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6325 struct proxy *target;
6326
Willy Tarreau56123282010-08-06 19:06:56 +02006327 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006328 continue;
6329
6330 if (trule->act_prm.trk_ctr.table.n)
6331 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6332 else
6333 target = curproxy;
6334
6335 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006336 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6337 curproxy->id, trule->act_prm.trk_ctr.table.n,
6338 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006339 cfgerr++;
6340 }
6341 else if (target->table.size == 0) {
6342 Alert("Proxy '%s': table '%s' used but not configured.\n",
6343 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6344 cfgerr++;
6345 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006346 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6347 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6348 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6349 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6350 cfgerr++;
6351 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006352 else {
6353 free(trule->act_prm.trk_ctr.table.n);
6354 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006355 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006356 * to pass a list of counters to track and allocate them right here using
6357 * stktable_alloc_data_type().
6358 */
6359 }
6360 }
6361
Willy Tarreaud1f96522010-08-03 19:34:32 +02006362 /* find the target table for 'tcp-request' layer 6 rules */
6363 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6364 struct proxy *target;
6365
Willy Tarreau56123282010-08-06 19:06:56 +02006366 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006367 continue;
6368
6369 if (trule->act_prm.trk_ctr.table.n)
6370 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6371 else
6372 target = curproxy;
6373
6374 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006375 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6376 curproxy->id, trule->act_prm.trk_ctr.table.n,
6377 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006378 cfgerr++;
6379 }
6380 else if (target->table.size == 0) {
6381 Alert("Proxy '%s': table '%s' used but not configured.\n",
6382 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6383 cfgerr++;
6384 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006385 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6386 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6387 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6388 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6389 cfgerr++;
6390 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006391 else {
6392 free(trule->act_prm.trk_ctr.table.n);
6393 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006394 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006395 * to pass a list of counters to track and allocate them right here using
6396 * stktable_alloc_data_type().
6397 */
6398 }
6399 }
6400
Emeric Brun32da3c42010-09-23 18:39:19 +02006401 if (curproxy->table.peers.name) {
6402 struct peers *curpeers = peers;
6403
6404 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6405 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6406 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006407 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006408 break;
6409 }
6410 }
6411
6412 if (!curpeers) {
6413 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6414 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006415 free((void *)curproxy->table.peers.name);
6416 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006417 cfgerr++;
6418 }
6419 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006420 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6421 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006422 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006423 cfgerr++;
6424 }
6425 }
6426
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006427 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006428 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006429 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6430 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6431 "proxy", curproxy->id);
6432 cfgerr++;
6433 goto out_uri_auth_compat;
6434 }
6435
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006436 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006437 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006438 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006439 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006440
Willy Tarreau95fa4692010-02-01 13:05:50 +01006441 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6442 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006443
6444 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006445 uri_auth_compat_req[i++] = "realm";
6446 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6447 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006448
Willy Tarreau95fa4692010-02-01 13:05:50 +01006449 uri_auth_compat_req[i++] = "unless";
6450 uri_auth_compat_req[i++] = "{";
6451 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6452 uri_auth_compat_req[i++] = "}";
6453 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006454
Willy Tarreauff011f22011-01-06 17:51:27 +01006455 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6456 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006457 cfgerr++;
6458 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006459 }
6460
Willy Tarreauff011f22011-01-06 17:51:27 +01006461 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006462
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006463 if (curproxy->uri_auth->auth_realm) {
6464 free(curproxy->uri_auth->auth_realm);
6465 curproxy->uri_auth->auth_realm = NULL;
6466 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006467
6468 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006469 }
6470out_uri_auth_compat:
6471
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006472 /* compile the log format */
6473 if (!(curproxy->cap & PR_CAP_FE)) {
6474 if (curproxy->logformat_string != default_http_log_format &&
6475 curproxy->logformat_string != default_tcp_log_format &&
6476 curproxy->logformat_string != clf_http_log_format)
6477 free(curproxy->logformat_string);
6478 curproxy->logformat_string = NULL;
6479 }
6480
6481 curproxy->conf.args.ctx = ARGC_LOG;
6482 if (curproxy->logformat_string)
6483 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
6484 SMP_VAL_FE_LOG_END);
6485
6486 curproxy->conf.args.ctx = ARGC_UIF;
6487 if (curproxy->uniqueid_format_string)
6488 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
6489 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
6490
6491 /* only now we can check if some args remain unresolved */
6492 cfgerr += smp_resolve_args(curproxy);
6493 if (!cfgerr)
6494 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006495
Willy Tarreau2738a142006-07-08 17:28:09 +02006496 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006497 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006498 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006499 (!curproxy->timeout.connect ||
6500 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006501 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006502 " | While not properly invalid, you will certainly encounter various problems\n"
6503 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006504 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006505 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006506 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006507 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006508
Willy Tarreau1fa31262007-12-03 00:36:16 +01006509 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6510 * We must still support older configurations, so let's find out whether those
6511 * parameters have been set or must be copied from contimeouts.
6512 */
6513 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006514 if (!curproxy->timeout.tarpit ||
6515 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006516 /* tarpit timeout not set. We search in the following order:
6517 * default.tarpit, curr.connect, default.connect.
6518 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006519 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006520 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006521 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006522 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006523 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006524 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006525 }
6526 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006527 (!curproxy->timeout.queue ||
6528 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006529 /* queue timeout not set. We search in the following order:
6530 * default.queue, curr.connect, default.connect.
6531 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006532 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006533 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006534 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006535 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006536 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006537 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006538 }
6539 }
6540
Willy Tarreau1620ec32011-08-06 17:05:02 +02006541 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006542 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6543 curproxy->check_req = (char *)malloc(curproxy->check_len);
6544 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006545 }
6546
Willy Tarreau193b8c62012-11-22 00:17:38 +01006547 /* ensure that cookie capture length is not too large */
6548 if (curproxy->capture_len >= global.tune.cookie_len) {
6549 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6550 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6551 err_code |= ERR_WARN;
6552 curproxy->capture_len = global.tune.cookie_len - 1;
6553 }
6554
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006555 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006556 if (curproxy->nb_req_cap) {
6557 if (curproxy->mode == PR_MODE_HTTP) {
6558 curproxy->req_cap_pool = create_pool("ptrcap",
6559 curproxy->nb_req_cap * sizeof(char *),
6560 MEM_F_SHARED);
6561 } else {
6562 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6563 proxy_type_str(curproxy), curproxy->id);
6564 err_code |= ERR_WARN;
6565 curproxy->to_log &= ~LW_REQHDR;
6566 curproxy->nb_req_cap = 0;
6567 }
6568 }
6569
6570 if (curproxy->nb_rsp_cap) {
6571 if (curproxy->mode == PR_MODE_HTTP) {
6572 curproxy->rsp_cap_pool = create_pool("ptrcap",
6573 curproxy->nb_rsp_cap * sizeof(char *),
6574 MEM_F_SHARED);
6575 } else {
6576 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6577 proxy_type_str(curproxy), curproxy->id);
6578 err_code |= ERR_WARN;
6579 curproxy->to_log &= ~LW_REQHDR;
6580 curproxy->nb_rsp_cap = 0;
6581 }
6582 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006583
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 /* first, we will invert the servers list order */
6585 newsrv = NULL;
6586 while (curproxy->srv) {
6587 struct server *next;
6588
6589 next = curproxy->srv->next;
6590 curproxy->srv->next = newsrv;
6591 newsrv = curproxy->srv;
6592 if (!next)
6593 break;
6594 curproxy->srv = next;
6595 }
6596
Willy Tarreaudd701652010-05-25 23:03:02 +02006597 /* assign automatic UIDs to servers which don't have one yet */
6598 next_id = 1;
6599 newsrv = curproxy->srv;
6600 while (newsrv != NULL) {
6601 if (!newsrv->puid) {
6602 /* server ID not set, use automatic numbering with first
6603 * spare entry starting with next_svid.
6604 */
6605 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6606 newsrv->conf.id.key = newsrv->puid = next_id;
6607 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6608 }
6609 next_id++;
6610 newsrv = newsrv->next;
6611 }
6612
Willy Tarreau20697042007-11-15 23:26:18 +01006613 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006614 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006615
Willy Tarreau62c3be22012-01-20 13:12:32 +01006616 /*
6617 * If this server supports a maxconn parameter, it needs a dedicated
6618 * tasks to fill the emptied slots when a connection leaves.
6619 * Also, resolve deferred tracking dependency if needed.
6620 */
6621 newsrv = curproxy->srv;
6622 while (newsrv != NULL) {
6623 if (newsrv->minconn > newsrv->maxconn) {
6624 /* Only 'minconn' was specified, or it was higher than or equal
6625 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6626 * this will avoid further useless expensive computations.
6627 */
6628 newsrv->maxconn = newsrv->minconn;
6629 } else if (newsrv->maxconn && !newsrv->minconn) {
6630 /* minconn was not specified, so we set it to maxconn */
6631 newsrv->minconn = newsrv->maxconn;
6632 }
6633
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006634#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006635 if (newsrv->use_ssl || newsrv->check.use_ssl)
6636 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006637#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006638
Willy Tarreau62c3be22012-01-20 13:12:32 +01006639 if (newsrv->trackit) {
6640 struct proxy *px;
6641 struct server *srv;
6642 char *pname, *sname;
6643
6644 pname = newsrv->trackit;
6645 sname = strrchr(pname, '/');
6646
6647 if (sname)
6648 *sname++ = '\0';
6649 else {
6650 sname = pname;
6651 pname = NULL;
6652 }
6653
6654 if (pname) {
6655 px = findproxy(pname, PR_CAP_BE);
6656 if (!px) {
6657 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6658 proxy_type_str(curproxy), curproxy->id,
6659 newsrv->id, pname);
6660 cfgerr++;
6661 goto next_srv;
6662 }
6663 } else
6664 px = curproxy;
6665
6666 srv = findserver(px, sname);
6667 if (!srv) {
6668 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6669 proxy_type_str(curproxy), curproxy->id,
6670 newsrv->id, sname);
6671 cfgerr++;
6672 goto next_srv;
6673 }
6674
6675 if (!(srv->state & SRV_CHECKED)) {
6676 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6677 "tracking as it does not have checks enabled.\n",
6678 proxy_type_str(curproxy), curproxy->id,
6679 newsrv->id, px->id, srv->id);
6680 cfgerr++;
6681 goto next_srv;
6682 }
6683
6684 if (curproxy != px &&
6685 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6686 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6687 "tracking: disable-on-404 option inconsistency.\n",
6688 proxy_type_str(curproxy), curproxy->id,
6689 newsrv->id, px->id, srv->id);
6690 cfgerr++;
6691 goto next_srv;
6692 }
6693
6694 /* if the other server is forced disabled, we have to do the same here */
6695 if (srv->state & SRV_MAINTAIN) {
6696 newsrv->state |= SRV_MAINTAIN;
6697 newsrv->state &= ~SRV_RUNNING;
6698 newsrv->health = 0;
6699 }
6700
6701 newsrv->track = srv;
6702 newsrv->tracknext = srv->tracknext;
6703 srv->tracknext = newsrv;
6704
6705 free(newsrv->trackit);
6706 newsrv->trackit = NULL;
6707 }
6708 next_srv:
6709 newsrv = newsrv->next;
6710 }
6711
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006712 /* We have to initialize the server lookup mechanism depending
6713 * on what LB algorithm was choosen.
6714 */
6715
6716 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6717 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6718 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006719 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6720 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6721 init_server_map(curproxy);
6722 } else {
6723 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6724 fwrr_init_server_groups(curproxy);
6725 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006726 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006727
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006728 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006729 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6730 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6731 fwlc_init_server_tree(curproxy);
6732 } else {
6733 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6734 fas_init_server_tree(curproxy);
6735 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006736 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006737
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006738 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006739 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6740 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6741 chash_init_server_tree(curproxy);
6742 } else {
6743 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6744 init_server_map(curproxy);
6745 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006746 break;
6747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006748
6749 if (curproxy->options & PR_O_LOGASAP)
6750 curproxy->to_log &= ~LW_BYTES;
6751
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006752 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006753 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006754 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6755 proxy_type_str(curproxy), curproxy->id);
6756 err_code |= ERR_WARN;
6757 }
6758
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006759 if (curproxy->mode != PR_MODE_HTTP) {
6760 int optnum;
6761
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006762 if (curproxy->uri_auth) {
6763 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6764 proxy_type_str(curproxy), curproxy->id);
6765 err_code |= ERR_WARN;
6766 curproxy->uri_auth = NULL;
6767 }
6768
Willy Tarreau87cf5142011-08-19 22:57:24 +02006769 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006770 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6771 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6772 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006773 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006774 }
6775
6776 if (curproxy->options & PR_O_ORGTO) {
6777 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6778 "originalto", proxy_type_str(curproxy), curproxy->id);
6779 err_code |= ERR_WARN;
6780 curproxy->options &= ~PR_O_ORGTO;
6781 }
6782
6783 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6784 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6785 (curproxy->cap & cfg_opts[optnum].cap) &&
6786 (curproxy->options & cfg_opts[optnum].val)) {
6787 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6788 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6789 err_code |= ERR_WARN;
6790 curproxy->options &= ~cfg_opts[optnum].val;
6791 }
6792 }
6793
6794 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6795 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6796 (curproxy->cap & cfg_opts2[optnum].cap) &&
6797 (curproxy->options2 & cfg_opts2[optnum].val)) {
6798 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6799 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6800 err_code |= ERR_WARN;
6801 curproxy->options2 &= ~cfg_opts2[optnum].val;
6802 }
6803 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006804
Willy Tarreauefa5f512010-03-30 20:13:29 +02006805#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006806 if (curproxy->conn_src.bind_hdr_occ) {
6807 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006808 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006809 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006810 err_code |= ERR_WARN;
6811 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006812#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006813 }
6814
Willy Tarreaubaaee002006-06-26 02:48:02 +02006815 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006816 * ensure that we're not cross-dressing a TCP server into HTTP.
6817 */
6818 newsrv = curproxy->srv;
6819 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006820 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006821 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6822 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006823 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006824 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006825
Willy Tarreau0cec3312011-10-31 13:49:26 +01006826 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6827 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6828 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6829 err_code |= ERR_WARN;
6830 }
6831
Willy Tarreauefa5f512010-03-30 20:13:29 +02006832#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006833 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6834 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006835 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 +01006836 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006837 err_code |= ERR_WARN;
6838 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006839#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006840 newsrv = newsrv->next;
6841 }
6842
Willy Tarreauc1a21672009-08-16 22:37:44 +02006843 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006844 if (!curproxy->accept)
6845 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006846
Willy Tarreauc1a21672009-08-16 22:37:44 +02006847 if (curproxy->tcp_req.inspect_delay ||
6848 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006849 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006850
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006851 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006852 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006853 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006854 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006855
6856 /* both TCP and HTTP must check switching rules */
6857 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6858 }
6859
6860 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006861 if (curproxy->tcp_req.inspect_delay ||
6862 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6863 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6864
Emeric Brun97679e72010-09-23 17:56:44 +02006865 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6866 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6867
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006868 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006869 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006870 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006871 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006872
6873 /* If the backend does requires RDP cookie persistence, we have to
6874 * enable the corresponding analyser.
6875 */
6876 if (curproxy->options2 & PR_O2_RDPC_PRST)
6877 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6878 }
6879
Emeric Brunc52962f2012-11-15 18:28:02 +01006880#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006881 /* Configure SSL for each bind line.
6882 * Note: if configuration fails at some point, the ->ctx member
6883 * remains NULL so that listeners can later detach.
6884 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006885 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006886 if (!bind_conf->is_ssl) {
6887 if (bind_conf->default_ctx) {
6888 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6889 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6890 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006891 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006892 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006893 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006894 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006895 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006896 cfgerr++;
6897 continue;
6898 }
6899
Emeric Brun4b3091e2012-09-24 15:48:52 +02006900 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006901 Alert("Unable to allocate SSL session cache.\n");
6902 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006903 continue;
6904 }
6905
Emeric Brunfc0421f2012-09-07 17:30:07 +02006906 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006907 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006908 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006909#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006910
Willy Tarreaue6b98942007-10-29 01:09:36 +01006911 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006912 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006913 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006914 if (!listener->luid) {
6915 /* listener ID not set, use automatic numbering with first
6916 * spare entry starting with next_luid.
6917 */
6918 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6919 listener->conf.id.key = listener->luid = next_id;
6920 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006921 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006922 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006923
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006924 /* enable separate counters */
6925 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6926 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006927 if (!listener->name)
6928 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006929 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006930
Willy Tarreaue6b98942007-10-29 01:09:36 +01006931 if (curproxy->options & PR_O_TCP_NOLING)
6932 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006933 if (!listener->maxconn)
6934 listener->maxconn = curproxy->maxconn;
6935 if (!listener->backlog)
6936 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006937 if (!listener->maxaccept)
6938 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6939
6940 /* we want to have an optimal behaviour on single process mode to
6941 * maximize the work at once, but in multi-process we want to keep
6942 * some fairness between processes, so we target half of the max
6943 * number of events to be balanced over all the processes the proxy
6944 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6945 * used to disable the limit.
6946 */
6947 if (listener->maxaccept > 0) {
6948 if (nbproc > 1)
6949 listener->maxaccept = (listener->maxaccept + 1) / 2;
6950 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6951 }
6952
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006953 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006954 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006955 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006956 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006957
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006958 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6959 listener->options |= LI_O_TCP_RULES;
6960
Willy Tarreaude3041d2010-05-31 10:56:17 +02006961 if (curproxy->mon_mask.s_addr)
6962 listener->options |= LI_O_CHK_MONNET;
6963
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006964 /* smart accept mode is automatic in HTTP mode */
6965 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006966 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006967 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6968 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006969 }
6970
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006971 /* Release unused SSL configs */
6972 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6973 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006974 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006975#ifdef USE_OPENSSL
6976 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006977 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006978 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006979 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006980 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006981#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006982 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006983
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006984 /* Check multi-process mode compatibility for the current proxy */
6985 if (global.nbproc > 1) {
6986 int nbproc = 0;
6987 if (curproxy->bind_proc) {
6988 int proc;
6989 for (proc = 0; proc < global.nbproc; proc++) {
6990 if (curproxy->bind_proc & (1 << proc)) {
6991 nbproc++;
6992 }
6993 }
6994 } else {
6995 nbproc = global.nbproc;
6996 }
6997 if (curproxy->table.peers.name) {
6998 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6999 curproxy->id);
7000 cfgerr++;
7001 }
7002 if (nbproc > 1) {
7003 if (curproxy->uri_auth) {
7004 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7005 curproxy->id);
7006 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7007 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7008 curproxy->id);
7009 }
7010 }
7011 if (curproxy->appsession_name) {
7012 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7013 curproxy->id);
7014 }
7015 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7016 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7017 curproxy->id);
7018 }
7019 }
7020 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007021
7022 /* create the task associated with the proxy */
7023 curproxy->task = task_new();
7024 if (curproxy->task) {
7025 curproxy->task->context = curproxy;
7026 curproxy->task->process = manage_proxy;
7027 /* no need to queue, it will be done automatically if some
7028 * listener gets limited.
7029 */
7030 curproxy->task->expire = TICK_ETERNITY;
7031 } else {
7032 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7033 curproxy->id);
7034 cfgerr++;
7035 }
7036
Willy Tarreaubaaee002006-06-26 02:48:02 +02007037 curproxy = curproxy->next;
7038 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007039
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007040 /* Check multi-process mode compatibility */
7041 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007042 if (global.stats_fe && !global.stats_fe->bind_proc) {
7043 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 +01007044 }
7045 }
7046
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007047 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7048 struct auth_users *curuser;
7049 int g;
7050
7051 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7052 unsigned int group_mask = 0;
7053 char *group = NULL;
7054
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007055 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007056 continue;
7057
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007058 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007059
7060 for (g = 0; g < curuserlist->grpcnt; g++)
7061 if (!strcmp(curuserlist->groups[g], group))
7062 break;
7063
7064 if (g == curuserlist->grpcnt) {
7065 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7066 curuserlist->name, group, curuser->user);
7067 err_code |= ERR_ALERT | ERR_FATAL;
7068 goto out;
7069 }
7070
7071 group_mask |= (1 << g);
7072 }
7073
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007074 free(curuser->u.groups);
7075 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007076 }
7077
7078 for (g = 0; g < curuserlist->grpcnt; g++) {
7079 char *user = NULL;
7080
7081 if (!curuserlist->groupusers[g])
7082 continue;
7083
7084 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7085 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7086 if (!strcmp(curuser->user, user))
7087 break;
7088
7089 if (!curuser) {
7090 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7091 curuserlist->name, user, curuserlist->groups[g]);
7092 err_code |= ERR_ALERT | ERR_FATAL;
7093 goto out;
7094 }
7095
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007096 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007097 }
7098
7099 free(curuserlist->groupusers[g]);
7100 }
7101
7102 free(curuserlist->groupusers);
7103
7104#ifdef DEBUG_AUTH
7105 for (g = 0; g < curuserlist->grpcnt; g++) {
7106 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7107
7108 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007109 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007110 fprintf(stderr, " %s", curuser->user);
7111 }
7112
7113 fprintf(stderr, "\n");
7114 }
7115#endif
7116
Willy Tarreaufbb78422011-06-05 15:38:35 +02007117 }
7118
7119 /* automatically compute fullconn if not set. We must not do it in the
7120 * loop above because cross-references are not yet fully resolved.
7121 */
7122 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7123 /* If <fullconn> is not set, let's set it to 10% of the sum of
7124 * the possible incoming frontend's maxconns.
7125 */
7126 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7127 struct proxy *fe;
7128 int total = 0;
7129
7130 /* sum up the number of maxconns of frontends which
7131 * reference this backend at least once or which are
7132 * the same one ('listen').
7133 */
7134 for (fe = proxy; fe; fe = fe->next) {
7135 struct switching_rule *rule;
7136 struct hdr_exp *exp;
7137 int found = 0;
7138
7139 if (!(fe->cap & PR_CAP_FE))
7140 continue;
7141
7142 if (fe == curproxy) /* we're on a "listen" instance */
7143 found = 1;
7144
7145 if (fe->defbe.be == curproxy) /* "default_backend" */
7146 found = 1;
7147
7148 /* check if a "use_backend" rule matches */
7149 if (!found) {
7150 list_for_each_entry(rule, &fe->switching_rules, list) {
7151 if (rule->be.backend == curproxy) {
7152 found = 1;
7153 break;
7154 }
7155 }
7156 }
7157
7158 /* check if a "reqsetbe" rule matches */
7159 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7160 if (exp->action == ACT_SETBE &&
7161 (struct proxy *)exp->replace == curproxy) {
7162 found = 1;
7163 break;
7164 }
7165 }
7166
7167 /* now we've checked all possible ways to reference a backend
7168 * from a frontend.
7169 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007170 if (!found)
7171 continue;
7172 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007173 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007174 /* we have the sum of the maxconns in <total>. We only
7175 * keep 10% of that sum to set the default fullconn, with
7176 * a hard minimum of 1 (to avoid a divide by zero).
7177 */
7178 curproxy->fullconn = (total + 9) / 10;
7179 if (!curproxy->fullconn)
7180 curproxy->fullconn = 1;
7181 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007182 }
7183
Willy Tarreau056f5682010-06-06 15:51:11 +02007184 /* initialize stick-tables on backend capable proxies. This must not
7185 * be done earlier because the data size may be discovered while parsing
7186 * other proxies.
7187 */
7188 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007189 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007190
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007191 /*
7192 * Recount currently required checks.
7193 */
7194
7195 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7196 int optnum;
7197
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007198 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7199 if (curproxy->options & cfg_opts[optnum].val)
7200 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007201
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007202 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7203 if (curproxy->options2 & cfg_opts2[optnum].val)
7204 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007205 }
7206
Willy Tarreau122541c2011-09-07 21:24:49 +02007207 if (peers) {
7208 struct peers *curpeers = peers, **last;
7209 struct peer *p, *pb;
7210
7211 /* Remove all peers sections which don't have a valid listener.
7212 * This can happen when a peers section is never referenced and
7213 * does not contain a local peer.
7214 */
7215 last = &peers;
7216 while (*last) {
7217 curpeers = *last;
7218 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007219 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007220 last = &curpeers->next;
7221 continue;
7222 }
7223
7224 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7225 curpeers->id, localpeer);
7226
7227 p = curpeers->remote;
7228 while (p) {
7229 pb = p->next;
7230 free(p->id);
7231 free(p);
7232 p = pb;
7233 }
7234
7235 /* Destroy and unlink this curpeers section.
7236 * Note: curpeers is backed up into *last.
7237 */
7238 free(curpeers->id);
7239 curpeers = curpeers->next;
7240 free(*last);
7241 *last = curpeers;
7242 }
7243 }
7244
Willy Tarreau34eb6712011-10-24 18:15:04 +02007245 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007246 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007247 MEM_F_SHARED);
7248
Willy Tarreaubb925012009-07-23 13:36:36 +02007249 if (cfgerr > 0)
7250 err_code |= ERR_ALERT | ERR_FATAL;
7251 out:
7252 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007253}
7254
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007255/*
7256 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7257 * parsing sessions.
7258 */
7259void cfg_register_keywords(struct cfg_kw_list *kwl)
7260{
7261 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7262}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007263
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007264/*
7265 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7266 */
7267void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7268{
7269 LIST_DEL(&kwl->list);
7270 LIST_INIT(&kwl->list);
7271}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007272
7273/*
7274 * Local variables:
7275 * c-indent-level: 8
7276 * c-basic-offset: 8
7277 * End:
7278 */