blob: 579dbcc530a7d7e915d9ab3ea5b1e81c1cc7013e [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 Tarreau2819e992013-12-13 14:41:10 +0100612 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200613 }
614 else if (!strcmp(args[0], "tune.maxrewrite")) {
615 if (*(args[1]) == 0) {
616 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
617 err_code |= ERR_ALERT | ERR_FATAL;
618 goto out;
619 }
620 global.tune.maxrewrite = atol(args[1]);
621 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
622 global.tune.maxrewrite = global.tune.bufsize / 2;
623 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100624 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
625 if (global.tune.client_rcvbuf != 0) {
626 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
627 err_code |= ERR_ALERT;
628 goto out;
629 }
630 if (*(args[1]) == 0) {
631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
634 }
635 global.tune.client_rcvbuf = atol(args[1]);
636 }
637 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
638 if (global.tune.server_rcvbuf != 0) {
639 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT;
641 goto out;
642 }
643 if (*(args[1]) == 0) {
644 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT | ERR_FATAL;
646 goto out;
647 }
648 global.tune.server_rcvbuf = atol(args[1]);
649 }
650 else if (!strcmp(args[0], "tune.sndbuf.client")) {
651 if (global.tune.client_sndbuf != 0) {
652 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT;
654 goto out;
655 }
656 if (*(args[1]) == 0) {
657 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
658 err_code |= ERR_ALERT | ERR_FATAL;
659 goto out;
660 }
661 global.tune.client_sndbuf = atol(args[1]);
662 }
663 else if (!strcmp(args[0], "tune.sndbuf.server")) {
664 if (global.tune.server_sndbuf != 0) {
665 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
666 err_code |= ERR_ALERT;
667 goto out;
668 }
669 if (*(args[1]) == 0) {
670 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674 global.tune.server_sndbuf = atol(args[1]);
675 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200676 else if (!strcmp(args[0], "tune.pipesize")) {
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.pipesize = atol(args[1]);
683 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100684 else if (!strcmp(args[0], "tune.http.cookielen")) {
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 global.tune.cookie_len = atol(args[1]) + 1;
691 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200692 else if (!strcmp(args[0], "tune.http.maxhdr")) {
693 if (*(args[1]) == 0) {
694 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
697 }
698 global.tune.max_http_hdr = atol(args[1]);
699 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100700 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
701#ifdef USE_ZLIB
702 if (*args[1]) {
703 global.tune.zlibmemlevel = atoi(args[1]);
704 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
705 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
706 file, linenum, args[0]);
707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
709 }
710 } else {
711 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
712 file, linenum, args[0]);
713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
715 }
716#else
717 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720#endif
721 }
722 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
723#ifdef USE_ZLIB
724 if (*args[1]) {
725 global.tune.zlibwindowsize = atoi(args[1]);
726 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
727 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
728 file, linenum, args[0]);
729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
731 }
732 } else {
733 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
734 file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738#else
739 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742#endif
743 }
William Lallemandf3747832012-11-09 12:33:10 +0100744 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
745 if (*args[1]) {
746 global.tune.comp_maxlevel = atoi(args[1]);
747 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
748 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
749 file, linenum, args[0]);
750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
752 }
753 } else {
754 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
755 file, linenum, args[0]);
756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
758 }
759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 else if (!strcmp(args[0], "uid")) {
761 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200762 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200763 err_code |= ERR_ALERT;
764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200765 }
766 if (*(args[1]) == 0) {
767 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 }
771 global.uid = atol(args[1]);
772 }
773 else if (!strcmp(args[0], "gid")) {
774 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200775 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200776 err_code |= ERR_ALERT;
777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200778 }
779 if (*(args[1]) == 0) {
780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200781 err_code |= ERR_ALERT | ERR_FATAL;
782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783 }
784 global.gid = atol(args[1]);
785 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200786 /* user/group name handling */
787 else if (!strcmp(args[0], "user")) {
788 struct passwd *ha_user;
789 if (global.uid != 0) {
790 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 err_code |= ERR_ALERT;
792 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200793 }
794 errno = 0;
795 ha_user = getpwnam(args[1]);
796 if (ha_user != NULL) {
797 global.uid = (int)ha_user->pw_uid;
798 }
799 else {
800 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 +0200801 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200802 }
803 }
804 else if (!strcmp(args[0], "group")) {
805 struct group *ha_group;
806 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200807 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200808 err_code |= ERR_ALERT;
809 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200810 }
811 errno = 0;
812 ha_group = getgrnam(args[1]);
813 if (ha_group != NULL) {
814 global.gid = (int)ha_group->gr_gid;
815 }
816 else {
817 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 +0200818 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200819 }
820 }
821 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828 global.nbproc = atol(args[1]);
829 }
830 else if (!strcmp(args[0], "maxconn")) {
831 if (global.maxconn != 0) {
832 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200833 err_code |= ERR_ALERT;
834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 }
836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
841 global.maxconn = atol(args[1]);
842#ifdef SYSTEM_MAXCONN
843 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
844 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);
845 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200846 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200847 }
848#endif /* SYSTEM_MAXCONN */
849 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200850 else if (!strcmp(args[0], "maxsslconn")) {
851#ifdef USE_OPENSSL
852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
856 }
857 global.maxsslconn = atol(args[1]);
858#else
Emeric Brun0914df82012-10-02 18:45:42 +0200859 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200862#endif
863 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200864 else if (!strcmp(args[0], "maxconnrate")) {
865 if (global.cps_lim != 0) {
866 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT;
868 goto out;
869 }
870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 global.cps_lim = atol(args[1]);
876 }
William Lallemandd85f9172012-11-09 17:05:39 +0100877 else if (!strcmp(args[0], "maxcomprate")) {
878 if (*(args[1]) == 0) {
879 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883 global.comp_rate_lim = atoi(args[1]) * 1024;
884 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100885 else if (!strcmp(args[0], "maxpipes")) {
886 if (global.maxpipes != 0) {
887 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200888 err_code |= ERR_ALERT;
889 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100890 }
891 if (*(args[1]) == 0) {
892 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100895 }
896 global.maxpipes = atol(args[1]);
897 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100898 else if (!strcmp(args[0], "maxzlibmem")) {
899 if (*(args[1]) == 0) {
900 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
William Lallemande3a7d992012-11-20 11:25:20 +0100904 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100905 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100906 else if (!strcmp(args[0], "maxcompcpuusage")) {
907 if (*(args[1]) == 0) {
908 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
909 err_code |= ERR_ALERT | ERR_FATAL;
910 goto out;
911 }
912 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100913 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100914 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918}
919
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 else if (!strcmp(args[0], "ulimit-n")) {
921 if (global.rlimit_nofile != 0) {
922 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200923 err_code |= ERR_ALERT;
924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 }
926 if (*(args[1]) == 0) {
927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 }
931 global.rlimit_nofile = atol(args[1]);
932 }
933 else if (!strcmp(args[0], "chroot")) {
934 if (global.chroot != NULL) {
935 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT;
937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 }
939 if (*(args[1]) == 0) {
940 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 }
944 global.chroot = strdup(args[1]);
945 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200946 else if (!strcmp(args[0], "description")) {
947 int i, len=0;
948 char *d;
949
950 if (!*args[1]) {
951 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
952 file, linenum, args[0]);
953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
955 }
956
957 for(i=1; *args[i]; i++)
958 len += strlen(args[i])+1;
959
960 if (global.desc)
961 free(global.desc);
962
963 global.desc = d = (char *)calloc(1, len);
964
965 d += sprintf(d, "%s", args[1]);
966 for(i=2; *args[i]; i++)
967 d += sprintf(d, " %s", args[i]);
968 }
969 else if (!strcmp(args[0], "node")) {
970 int i;
971 char c;
972
973 for (i=0; args[1][i]; i++) {
974 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100975 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
976 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200977 break;
978 }
979
980 if (!i || args[1][i]) {
981 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
982 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
983 file, linenum, args[0]);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
987
988 if (global.node)
989 free(global.node);
990
991 global.node = strdup(args[1]);
992 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 else if (!strcmp(args[0], "pidfile")) {
994 if (global.pidfile != NULL) {
995 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200996 err_code |= ERR_ALERT;
997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 }
999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003 }
1004 global.pidfile = strdup(args[1]);
1005 }
Emeric Bruned760922010-10-22 17:59:25 +02001006 else if (!strcmp(args[0], "unix-bind")) {
1007 int cur_arg = 1;
1008 while (*(args[cur_arg])) {
1009 if (!strcmp(args[cur_arg], "prefix")) {
1010 if (global.unix_bind.prefix != NULL) {
1011 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1012 err_code |= ERR_ALERT;
1013 cur_arg += 2;
1014 continue;
1015 }
1016
1017 if (*(args[cur_arg+1]) == 0) {
1018 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
1021 }
1022 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1023 cur_arg += 2;
1024 continue;
1025 }
1026
1027 if (!strcmp(args[cur_arg], "mode")) {
1028
1029 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1030 cur_arg += 2;
1031 continue;
1032 }
1033
1034 if (!strcmp(args[cur_arg], "uid")) {
1035
1036 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1037 cur_arg += 2;
1038 continue;
1039 }
1040
1041 if (!strcmp(args[cur_arg], "gid")) {
1042
1043 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1044 cur_arg += 2;
1045 continue;
1046 }
1047
1048 if (!strcmp(args[cur_arg], "user")) {
1049 struct passwd *user;
1050
1051 user = getpwnam(args[cur_arg + 1]);
1052 if (!user) {
1053 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1054 file, linenum, args[0], args[cur_arg + 1 ]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058
1059 global.unix_bind.ux.uid = user->pw_uid;
1060 cur_arg += 2;
1061 continue;
1062 }
1063
1064 if (!strcmp(args[cur_arg], "group")) {
1065 struct group *group;
1066
1067 group = getgrnam(args[cur_arg + 1]);
1068 if (!group) {
1069 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1070 file, linenum, args[0], args[cur_arg + 1 ]);
1071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
1073 }
1074
1075 global.unix_bind.ux.gid = group->gr_gid;
1076 cur_arg += 2;
1077 continue;
1078 }
1079
Willy Tarreaub48f9582011-09-05 01:17:06 +02001080 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001081 file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085 }
William Lallemand0f99e342011-10-12 17:50:54 +02001086 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1087 /* delete previous herited or defined syslog servers */
1088 struct logsrv *back;
1089 struct logsrv *tmp;
1090
1091 if (*(args[1]) != 0) {
1092 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
1095 }
1096
1097 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1098 LIST_DEL(&tmp->list);
1099 free(tmp);
1100 }
1101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001103 struct sockaddr_storage *sk;
1104 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001105 struct logsrv *logsrv;
1106
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 if (*(args[1]) == 0 || *(args[2]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001111 }
William Lallemand0f99e342011-10-12 17:50:54 +02001112
1113 logsrv = calloc(1, sizeof(struct logsrv));
1114
1115 logsrv->facility = get_log_facility(args[2]);
1116 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001118 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001119 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 }
1121
William Lallemand0f99e342011-10-12 17:50:54 +02001122 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001124 logsrv->level = get_log_level(args[3]);
1125 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001126 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001128 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 }
1130 }
1131
William Lallemand0f99e342011-10-12 17:50:54 +02001132 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001133 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001134 logsrv->minlvl = get_log_level(args[4]);
1135 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001136 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001137 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001138 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001139 }
1140 }
1141
Willy Tarreau902636f2013-03-10 19:44:48 +01001142 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001143 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001144 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001145 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001146 free(logsrv);
1147 goto out;
1148 }
1149 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001150
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001151 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001152 if (port1 != port2) {
1153 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1154 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001155 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001156 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001157 goto out;
1158 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001159
William Lallemand0f99e342011-10-12 17:50:54 +02001160 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001161 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001162 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001163 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164
William Lallemand0f99e342011-10-12 17:50:54 +02001165 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001166 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001167 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1168 char *name;
1169 int len;
1170
1171 if (global.log_send_hostname != NULL) {
1172 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1173 err_code |= ERR_ALERT;
1174 goto out;
1175 }
1176
1177 if (*(args[1]))
1178 name = args[1];
1179 else
1180 name = hostname;
1181
1182 len = strlen(name);
1183
1184 /* We'll add a space after the name to respect the log format */
1185 free(global.log_send_hostname);
1186 global.log_send_hostname = malloc(len + 2);
1187 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1188 }
Kevinm48936af2010-12-22 16:08:21 +00001189 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1190 if (*(args[1]) == 0) {
1191 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
1195 free(global.log_tag);
1196 global.log_tag = strdup(args[1]);
1197 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001198 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1199 if (global.spread_checks != 0) {
1200 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT;
1202 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001203 }
1204 if (*(args[1]) == 0) {
1205 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001208 }
1209 global.spread_checks = atol(args[1]);
1210 if (global.spread_checks < 0 || global.spread_checks > 50) {
1211 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001212 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001215 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1216#ifdef USE_CPU_AFFINITY
1217 int cur_arg, i;
1218 unsigned int proc = 0;
1219 unsigned long cpus = 0;
1220
1221 if (strcmp(args[1], "all") == 0)
1222 proc = 0xFFFFFFFF;
1223 else if (strcmp(args[1], "odd") == 0)
1224 proc = 0x55555555;
1225 else if (strcmp(args[1], "even") == 0)
1226 proc = 0xAAAAAAAA;
1227 else {
1228 proc = atoi(args[1]);
1229 if (proc >= 1 && proc <= 32)
1230 proc = 1 << (proc - 1);
1231 }
1232
1233 if (!proc || !*args[2]) {
1234 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",
1235 file, linenum, args[0]);
1236 err_code |= ERR_ALERT | ERR_FATAL;
1237 goto out;
1238 }
1239
1240 cur_arg = 2;
1241 while (*args[cur_arg]) {
1242 unsigned int low, high;
1243
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001244 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001245 char *dash = strchr(args[cur_arg], '-');
1246
1247 low = high = str2uic(args[cur_arg]);
1248 if (dash)
1249 high = str2uic(dash + 1);
1250
1251 if (high < low) {
1252 unsigned int swap = low;
1253 low = high;
1254 high = swap;
1255 }
1256
1257 if (low < 0 || high >= sizeof(long) * 8) {
1258 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1259 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263
1264 while (low <= high)
1265 cpus |= 1UL << low++;
1266 }
1267 else {
1268 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1269 file, linenum, args[0], args[cur_arg]);
1270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
1272 }
1273 cur_arg++;
1274 }
1275 for (i = 0; i < 32; i++)
1276 if (proc & (1 << i))
1277 global.cpu_map[i] = cpus;
1278#else
1279 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
1282#endif
1283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001285 struct cfg_kw_list *kwl;
1286 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001287 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001288
1289 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1290 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1291 if (kwl->kw[index].section != CFG_GLOBAL)
1292 continue;
1293 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001294 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001295 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001296 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001297 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001298 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001299 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001300 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001301 err_code |= ERR_WARN;
1302 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001303 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001304 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001305 }
1306 }
1307 }
1308
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001310 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001312
Willy Tarreau058e9072009-07-20 09:30:05 +02001313 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001314 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001315 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001316}
1317
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001318void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001320 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001321 defproxy.mode = PR_MODE_TCP;
1322 defproxy.state = PR_STNEW;
1323 defproxy.maxconn = cfg_maxpconn;
1324 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001325
Simon Horman66183002013-02-23 10:16:43 +09001326 defproxy.defsrv.check.inter = DEF_CHKINTR;
1327 defproxy.defsrv.check.fastinter = 0;
1328 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001329 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1330 defproxy.defsrv.agent.fastinter = 0;
1331 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001332 defproxy.defsrv.check.rise = DEF_RISETIME;
1333 defproxy.defsrv.check.fall = DEF_FALLTIME;
1334 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1335 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001336 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001337 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001338 defproxy.defsrv.maxqueue = 0;
1339 defproxy.defsrv.minconn = 0;
1340 defproxy.defsrv.maxconn = 0;
1341 defproxy.defsrv.slowstart = 0;
1342 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1343 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1344 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001345}
1346
Willy Tarreauade5ec42010-01-28 19:33:49 +01001347
1348static int create_cond_regex_rule(const char *file, int line,
1349 struct proxy *px, int dir, int action, int flags,
1350 const char *cmd, const char *reg, const char *repl,
1351 const char **cond_start)
1352{
1353 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001354 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001355 const char *err;
1356 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001357 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001358
1359 if (px == &defproxy) {
1360 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto err;
1363 }
1364
1365 if (*reg == 0) {
1366 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1367 err_code |= ERR_ALERT | ERR_FATAL;
1368 goto err;
1369 }
1370
1371 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1372 err_code |= ERR_WARN;
1373
Willy Tarreau5321c422010-01-28 20:35:13 +01001374 if (cond_start &&
1375 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001376 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1377 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1378 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto err;
1381 }
1382 }
1383 else if (cond_start && **cond_start) {
1384 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1385 file, line, cmd, *cond_start);
1386 err_code |= ERR_ALERT | ERR_FATAL;
1387 goto err;
1388 }
1389
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001390 err_code |= warnif_cond_conflicts(cond,
1391 (dir == SMP_OPT_DIR_REQ) ?
1392 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1393 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1394 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001395
Willy Tarreauade5ec42010-01-28 19:33:49 +01001396 preg = calloc(1, sizeof(regex_t));
1397 if (!preg) {
1398 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1399 err_code = ERR_ALERT | ERR_FATAL;
1400 goto err;
1401 }
1402
1403 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1404 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1405 err_code = ERR_ALERT | ERR_FATAL;
1406 goto err;
1407 }
1408
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001409 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001410 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001411 if (repl && err) {
1412 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1413 file, line, cmd, *err);
1414 err_code |= ERR_ALERT | ERR_FATAL;
1415 goto err;
1416 }
1417
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001418 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001419 err_code |= ERR_WARN;
1420
Willy Tarreauf4068b62012-05-08 17:37:49 +02001421 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001422 return err_code;
1423 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001424 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001425 free(preg);
1426 return err_code;
1427}
1428
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001430 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001431 * Returns the error code, 0 if OK, or any combination of :
1432 * - ERR_ABORT: must abort ASAP
1433 * - ERR_FATAL: we can continue parsing but not start the service
1434 * - ERR_WARN: a warning has been emitted
1435 * - ERR_ALERT: an alert has been emitted
1436 * Only the two first ones can stop processing, the two others are just
1437 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001439int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1440{
1441 static struct peers *curpeers = NULL;
1442 struct peer *newpeer = NULL;
1443 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001444 struct bind_conf *bind_conf;
1445 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001446 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001447 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001448
1449 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001450 if (!*args[1]) {
1451 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1452 err_code |= ERR_ALERT | ERR_FATAL;
1453 goto out;
1454 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001455
1456 err = invalid_char(args[1]);
1457 if (err) {
1458 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1459 file, linenum, *err, args[0], args[1]);
1460 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001461 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001462 }
1463
1464 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1465 /*
1466 * If there are two proxies with the same name only following
1467 * combinations are allowed:
1468 */
1469 if (strcmp(curpeers->id, args[1]) == 0) {
1470 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1471 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1472 err_code |= ERR_WARN;
1473 }
1474 }
1475
1476 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1477 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1478 err_code |= ERR_ALERT | ERR_ABORT;
1479 goto out;
1480 }
1481
1482 curpeers->next = peers;
1483 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001484 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001485 curpeers->conf.line = linenum;
1486 curpeers->last_change = now.tv_sec;
1487 curpeers->id = strdup(args[1]);
1488 }
1489 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001490 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001491 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001492 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001493
1494 if (!*args[2]) {
1495 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1496 file, linenum, args[0]);
1497 err_code |= ERR_ALERT | ERR_FATAL;
1498 goto out;
1499 }
1500
1501 err = invalid_char(args[1]);
1502 if (err) {
1503 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1504 file, linenum, *err, args[1]);
1505 err_code |= ERR_ALERT | ERR_FATAL;
1506 goto out;
1507 }
1508
1509 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1510 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1511 err_code |= ERR_ALERT | ERR_ABORT;
1512 goto out;
1513 }
1514
1515 /* the peers are linked backwards first */
1516 curpeers->count++;
1517 newpeer->next = curpeers->remote;
1518 curpeers->remote = newpeer;
1519 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001520 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001521 newpeer->conf.line = linenum;
1522
1523 newpeer->last_change = now.tv_sec;
1524 newpeer->id = strdup(args[1]);
1525
Willy Tarreau902636f2013-03-10 19:44:48 +01001526 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001527 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001528 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001531 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001532
1533 proto = protocol_by_family(sk->ss_family);
1534 if (!proto || !proto->connect) {
1535 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1536 file, linenum, args[0], args[1]);
1537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001540
1541 if (port1 != port2) {
1542 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed 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 }
1547
Willy Tarreau2aa38802013-02-20 19:20:59 +01001548 if (!port1) {
1549 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1550 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001551 err_code |= ERR_ALERT | ERR_FATAL;
1552 goto out;
1553 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001554
Emeric Brun32da3c42010-09-23 18:39:19 +02001555 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001556 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001557 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001558 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001559
Emeric Brun32da3c42010-09-23 18:39:19 +02001560 if (strcmp(newpeer->id, localpeer) == 0) {
1561 /* Current is local peer, it define a frontend */
1562 newpeer->local = 1;
1563
1564 if (!curpeers->peers_fe) {
1565 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1566 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1567 err_code |= ERR_ALERT | ERR_ABORT;
1568 goto out;
1569 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001570
Willy Tarreau237250c2011-07-29 01:49:03 +02001571 init_new_proxy(curpeers->peers_fe);
1572 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001573
1574 curpeers->peers_fe->last_change = now.tv_sec;
1575 curpeers->peers_fe->id = strdup(args[1]);
1576 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001577 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001578 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1579 curpeers->peers_fe->timeout.connect = 5000;
1580 curpeers->peers_fe->accept = peer_accept;
1581 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001582 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1583 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001584
1585 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1586
Willy Tarreau902636f2013-03-10 19:44:48 +01001587 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1588 if (errmsg && *errmsg) {
1589 indent_msg(&errmsg, 2);
1590 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001591 }
1592 else
1593 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1594 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001595 err_code |= ERR_FATAL;
1596 goto out;
1597 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001598
1599 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1600 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1601 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1602 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1603 l->accept = session_accept;
1604 l->handler = process_session;
1605 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1606 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1607 global.maxsock += l->maxconn;
1608 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001609 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001610 else {
1611 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1612 file, linenum, args[0], args[1],
1613 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1614 err_code |= ERR_FATAL;
1615 goto out;
1616 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001617 }
1618 } /* neither "peer" nor "peers" */
1619 else if (*args[0] != 0) {
1620 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
1623 }
1624
1625out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001626 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001627 return err_code;
1628}
1629
Simon Horman69d29f92013-02-23 15:14:19 +09001630static int init_check(struct check *check, int type, const char * file, int linenum)
1631{
1632 check->type = type;
1633
1634 /* Allocate buffer for requests... */
1635 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1636 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1637 return ERR_ALERT | ERR_ABORT;
1638 }
1639 check->bi->size = global.tune.chksize;
1640
1641 /* Allocate buffer for responses... */
1642 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1643 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1644 return ERR_ALERT | ERR_ABORT;
1645 }
1646 check->bo->size = global.tune.chksize;
1647
1648 /* Allocate buffer for partial results... */
1649 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1650 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1651 return ERR_ALERT | ERR_ABORT;
1652 }
1653
1654 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1655
1656 return 0;
1657}
Emeric Brun32da3c42010-09-23 18:39:19 +02001658
Willy Tarreau3842f002009-06-14 11:39:52 +02001659int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660{
1661 static struct proxy *curproxy = NULL;
1662 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001663 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001664 int rc;
1665 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001666 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001667 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001668 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001669 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001670 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001671
Willy Tarreau977b8e42006-12-29 14:19:17 +01001672 if (!strcmp(args[0], "listen"))
1673 rc = PR_CAP_LISTEN;
1674 else if (!strcmp(args[0], "frontend"))
1675 rc = PR_CAP_FE | PR_CAP_RS;
1676 else if (!strcmp(args[0], "backend"))
1677 rc = PR_CAP_BE | PR_CAP_RS;
1678 else if (!strcmp(args[0], "ruleset"))
1679 rc = PR_CAP_RS;
1680 else
1681 rc = PR_CAP_NONE;
1682
1683 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684 if (!*args[1]) {
1685 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1686 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1687 file, linenum, args[0]);
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 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001691
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001692 err = invalid_char(args[1]);
1693 if (err) {
1694 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1695 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001696 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001697 }
1698
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001699 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1700 /*
1701 * If there are two proxies with the same name only following
1702 * combinations are allowed:
1703 *
1704 * listen backend frontend ruleset
1705 * listen - - - -
1706 * backend - - OK -
1707 * frontend - OK - -
1708 * ruleset - - - -
1709 */
1710
1711 if (!strcmp(curproxy->id, args[1]) &&
1712 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1713 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001714 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1715 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1716 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001717 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001718 }
1719 }
1720
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1722 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001723 err_code |= ERR_ALERT | ERR_ABORT;
1724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001726
Willy Tarreau97cb7802010-01-03 20:23:58 +01001727 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 curproxy->next = proxy;
1729 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001730 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1731 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001732 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001734 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001735
1736 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001737 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001738 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001739
Willy Tarreau4348fad2012-09-20 16:48:07 +02001740 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1741
Willy Tarreau902636f2013-03-10 19:44:48 +01001742 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1743 if (errmsg && *errmsg) {
1744 indent_msg(&errmsg, 2);
1745 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001746 }
1747 else
1748 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1749 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_FATAL;
1751 goto out;
1752 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001753
Willy Tarreau4348fad2012-09-20 16:48:07 +02001754 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001755 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 }
1758
1759 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001760 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001761 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001762
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001765 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001766 curproxy->no_options = defproxy.no_options;
1767 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001768 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001769 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001770 curproxy->except_net = defproxy.except_net;
1771 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001772 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001773 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001775 if (defproxy.fwdfor_hdr_len) {
1776 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1777 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1778 }
1779
Willy Tarreaub86db342009-11-30 11:50:16 +01001780 if (defproxy.orgto_hdr_len) {
1781 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1782 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1783 }
1784
Mark Lamourinec2247f02012-01-04 13:02:01 -05001785 if (defproxy.server_id_hdr_len) {
1786 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1787 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1788 }
1789
Willy Tarreau977b8e42006-12-29 14:19:17 +01001790 if (curproxy->cap & PR_CAP_FE) {
1791 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001792 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001793 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001794
1795 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001796 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1797 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001798
1799 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802 if (curproxy->cap & PR_CAP_BE) {
1803 curproxy->fullconn = defproxy.fullconn;
1804 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001806 if (defproxy.check_req) {
1807 curproxy->check_req = calloc(1, defproxy.check_len);
1808 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1809 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001812 if (defproxy.expect_str) {
1813 curproxy->expect_str = strdup(defproxy.expect_str);
1814 if (defproxy.expect_regex) {
1815 /* note: this regex is known to be valid */
1816 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1817 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1818 }
1819 }
1820
Willy Tarreau67402132012-05-31 20:40:20 +02001821 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001822 if (defproxy.cookie_name)
1823 curproxy->cookie_name = strdup(defproxy.cookie_name);
1824 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001825 if (defproxy.cookie_domain)
1826 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001827
Willy Tarreau31936852010-10-06 16:59:56 +02001828 if (defproxy.cookie_maxidle)
1829 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1830
1831 if (defproxy.cookie_maxlife)
1832 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1833
Emeric Brun647caf12009-06-30 17:57:00 +02001834 if (defproxy.rdp_cookie_name)
1835 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1836 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1837
Willy Tarreau01732802007-11-01 22:48:15 +01001838 if (defproxy.url_param_name)
1839 curproxy->url_param_name = strdup(defproxy.url_param_name);
1840 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001841
Benoitaffb4812009-03-25 13:02:10 +01001842 if (defproxy.hh_name)
1843 curproxy->hh_name = strdup(defproxy.hh_name);
1844 curproxy->hh_len = defproxy.hh_len;
1845 curproxy->hh_match_domain = defproxy.hh_match_domain;
1846
Willy Tarreauef9a3602012-12-08 22:29:20 +01001847 if (defproxy.conn_src.iface_name)
1848 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1849 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001850 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001851#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001852 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001853#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001856 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001857 if (defproxy.capture_name)
1858 curproxy->capture_name = strdup(defproxy.capture_name);
1859 curproxy->capture_namelen = defproxy.capture_namelen;
1860 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862
Willy Tarreau977b8e42006-12-29 14:19:17 +01001863 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001864 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001865 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001866 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001867 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001868 curproxy->uri_auth = defproxy.uri_auth;
1869 curproxy->mon_net = defproxy.mon_net;
1870 curproxy->mon_mask = defproxy.mon_mask;
1871 if (defproxy.monitor_uri)
1872 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1873 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001874 if (defproxy.defbe.name)
1875 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001876
1877 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001878 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1879 if (curproxy->conf.logformat_string &&
1880 curproxy->conf.logformat_string != default_http_log_format &&
1881 curproxy->conf.logformat_string != default_tcp_log_format &&
1882 curproxy->conf.logformat_string != clf_http_log_format)
1883 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1884
1885 if (defproxy.conf.lfs_file) {
1886 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1887 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1888 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001889 }
1890
1891 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001892 curproxy->timeout.connect = defproxy.timeout.connect;
1893 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001894 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001895 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001896 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001897 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001898 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001899 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001900 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001901 }
1902
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001904
1905 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001906 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001907 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001908 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001909 LIST_INIT(&node->list);
1910 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1911 }
1912
Willy Tarreau62a61232013-04-12 18:13:46 +02001913 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1914 if (curproxy->conf.uniqueid_format_string)
1915 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1916
1917 if (defproxy.conf.uif_file) {
1918 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1919 curproxy->conf.uif_line = defproxy.conf.uif_line;
1920 }
William Lallemanda73203e2012-03-12 12:48:57 +01001921
1922 /* copy default header unique id */
1923 if (defproxy.header_unique_id)
1924 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1925
William Lallemand82fe75c2012-10-23 10:25:10 +02001926 /* default compression options */
1927 if (defproxy.comp != NULL) {
1928 curproxy->comp = calloc(1, sizeof(struct comp));
1929 curproxy->comp->algos = defproxy.comp->algos;
1930 curproxy->comp->types = defproxy.comp->types;
1931 }
1932
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001934 curproxy->conf.used_listener_id = EB_ROOT;
1935 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001936
Willy Tarreau93893792009-07-23 13:19:11 +02001937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 }
1939 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1940 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001941 /* FIXME-20070101: we should do this too at the end of the
1942 * config parsing to free all default values.
1943 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001944 free(defproxy.check_req);
1945 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001946 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001947 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001948 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001949 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001950 free(defproxy.capture_name);
1951 free(defproxy.monitor_uri);
1952 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001953 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001954 free(defproxy.fwdfor_hdr_name);
1955 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001956 free(defproxy.orgto_hdr_name);
1957 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001958 free(defproxy.server_id_hdr_name);
1959 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001960 free(defproxy.expect_str);
1961 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001962
Willy Tarreau62a61232013-04-12 18:13:46 +02001963 if (defproxy.conf.logformat_string != default_http_log_format &&
1964 defproxy.conf.logformat_string != default_tcp_log_format &&
1965 defproxy.conf.logformat_string != clf_http_log_format)
1966 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001967
Willy Tarreau62a61232013-04-12 18:13:46 +02001968 free(defproxy.conf.uniqueid_format_string);
1969 free(defproxy.conf.lfs_file);
1970 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001971
Willy Tarreaua534fea2008-08-03 12:19:50 +02001972 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001973 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001974
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975 /* we cannot free uri_auth because it might already be used */
1976 init_default_instance();
1977 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001978 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1979 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001980 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 }
1983 else if (curproxy == NULL) {
1984 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001985 err_code |= ERR_ALERT | ERR_FATAL;
1986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001988
1989 /* update the current file and line being parsed */
1990 curproxy->conf.args.file = curproxy->conf.file;
1991 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001992
1993 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001995 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001996 int cur_arg;
1997
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998 if (curproxy == &defproxy) {
1999 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002003 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002004 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005
Willy Tarreau24709282013-03-10 21:32:12 +01002006 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002007 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002011 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002012
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002013 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002014
2015 /* use default settings for unix sockets */
2016 bind_conf->ux.uid = global.unix_bind.ux.uid;
2017 bind_conf->ux.gid = global.unix_bind.ux.gid;
2018 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002019
2020 /* NOTE: the following line might create several listeners if there
2021 * are comma-separated IPs or port ranges. So all further processing
2022 * will have to be applied to all listeners created after last_listen.
2023 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002024 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2025 if (errmsg && *errmsg) {
2026 indent_msg(&errmsg, 2);
2027 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002028 }
2029 else
2030 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2031 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_ALERT | ERR_FATAL;
2033 goto out;
2034 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002035
Willy Tarreau4348fad2012-09-20 16:48:07 +02002036 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2037 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002038 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002039 }
2040
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002041 cur_arg = 2;
2042 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002043 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002044 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002045 char *err;
2046
Willy Tarreau26982662012-09-12 23:17:10 +02002047 kw = bind_find_kw(args[cur_arg]);
2048 if (kw) {
2049 char *err = NULL;
2050 int code;
2051
2052 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002053 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2054 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002055 cur_arg += 1 + kw->skip ;
2056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
2058 }
2059
Willy Tarreau4348fad2012-09-20 16:48:07 +02002060 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002061 err_code |= code;
2062
2063 if (code) {
2064 if (err && *err) {
2065 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002066 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002067 }
2068 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002069 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2070 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002071 if (code & ERR_FATAL) {
2072 free(err);
2073 cur_arg += 1 + kw->skip;
2074 goto out;
2075 }
2076 }
2077 free(err);
2078 cur_arg += 1 + kw->skip;
2079 continue;
2080 }
2081
Willy Tarreau8638f482012-09-18 18:01:17 +02002082 err = NULL;
2083 if (!bind_dumped) {
2084 bind_dump_kws(&err);
2085 indent_msg(&err, 4);
2086 bind_dumped = 1;
2087 }
2088
2089 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2090 file, linenum, args[0], args[1], args[cur_arg],
2091 err ? " Registered keywords :" : "", err ? err : "");
2092 free(err);
2093
Willy Tarreau93893792009-07-23 13:19:11 +02002094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002096 }
Willy Tarreau93893792009-07-23 13:19:11 +02002097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 }
2099 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2100 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2101 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2102 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002106 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002107 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002108
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 /* flush useless bits */
2110 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002113 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002114 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002115 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002116
Willy Tarreau1c47f852006-07-09 08:22:27 +02002117 if (!*args[1]) {
2118 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2119 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002122 }
2123
Willy Tarreaua534fea2008-08-03 12:19:50 +02002124 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002125 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002126 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002127 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002128 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2129
Willy Tarreau93893792009-07-23 13:19:11 +02002130 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2133 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2134 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2135 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2136 else {
2137 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002138 err_code |= ERR_ALERT | ERR_FATAL;
2139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 }
2141 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002142 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002143 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002144
2145 if (curproxy == &defproxy) {
2146 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2147 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_ALERT | ERR_FATAL;
2149 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002150 }
2151
2152 if (!*args[1]) {
2153 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2154 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002157 }
2158
2159 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002160 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002161
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002162 if (curproxy->uuid <= 0) {
2163 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002164 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002167 }
2168
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002169 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2170 if (node) {
2171 struct proxy *target = container_of(node, struct proxy, conf.id);
2172 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2173 file, linenum, proxy_type_str(curproxy), curproxy->id,
2174 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002179 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002180 else if (!strcmp(args[0], "description")) {
2181 int i, len=0;
2182 char *d;
2183
Cyril Bonté99ed3272010-01-24 23:29:44 +01002184 if (curproxy == &defproxy) {
2185 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2186 file, linenum, args[0]);
2187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
2189 }
2190
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002191 if (!*args[1]) {
2192 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2193 file, linenum, args[0]);
2194 return -1;
2195 }
2196
2197 for(i=1; *args[i]; i++)
2198 len += strlen(args[i])+1;
2199
2200 d = (char *)calloc(1, len);
2201 curproxy->desc = d;
2202
2203 d += sprintf(d, "%s", args[1]);
2204 for(i=2; *args[i]; i++)
2205 d += sprintf(d, " %s", args[i]);
2206
2207 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002208 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2209 curproxy->state = PR_STSTOPPED;
2210 }
2211 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2212 curproxy->state = PR_STNEW;
2213 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002214 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2215 int cur_arg = 1;
2216 unsigned int set = 0;
2217
2218 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002219 unsigned int low, high;
2220
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002221 if (strcmp(args[cur_arg], "all") == 0) {
2222 set = 0;
2223 break;
2224 }
2225 else if (strcmp(args[cur_arg], "odd") == 0) {
2226 set |= 0x55555555;
2227 }
2228 else if (strcmp(args[cur_arg], "even") == 0) {
2229 set |= 0xAAAAAAAA;
2230 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002231 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002232 char *dash = strchr(args[cur_arg], '-');
2233
2234 low = high = str2uic(args[cur_arg]);
2235 if (dash)
2236 high = str2uic(dash + 1);
2237
2238 if (high < low) {
2239 unsigned int swap = low;
2240 low = high;
2241 high = swap;
2242 }
2243
2244 if (low < 1 || high > 32) {
2245 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002246 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002247 err_code |= ERR_ALERT | ERR_FATAL;
2248 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002249 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002250
2251 if (high > global.nbproc) {
2252 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2253 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002255 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002256 while (low <= high)
2257 set |= 1 << (low++ - 1);
2258 }
2259 else {
2260 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2261 file, linenum, args[0]);
2262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002264 }
2265 cur_arg++;
2266 }
2267 curproxy->bind_proc = set;
2268 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002269 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002270 if (curproxy == &defproxy) {
2271 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002274 }
2275
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002276 err = invalid_char(args[1]);
2277 if (err) {
2278 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2279 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002280 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002281 }
2282
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002283 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002284 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2285 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002288 }
2289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2291 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292
Willy Tarreau977b8e42006-12-29 14:19:17 +01002293 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 if (*(args[1]) == 0) {
2297 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002302
Willy Tarreau67402132012-05-31 20:40:20 +02002303 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002304 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002305 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002306 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002307 curproxy->cookie_name = strdup(args[1]);
2308 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002309
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310 cur_arg = 2;
2311 while (*(args[cur_arg])) {
2312 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002313 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 }
2315 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002316 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 }
2318 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002319 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 }
2321 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002322 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 }
2324 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002325 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002327 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002328 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002331 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002333 else if (!strcmp(args[cur_arg], "httponly")) {
2334 curproxy->ck_opts |= PR_CK_HTTPONLY;
2335 }
2336 else if (!strcmp(args[cur_arg], "secure")) {
2337 curproxy->ck_opts |= PR_CK_SECURE;
2338 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002339 else if (!strcmp(args[cur_arg], "domain")) {
2340 if (!*args[cur_arg + 1]) {
2341 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2342 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002345 }
2346
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002347 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002348 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002349 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2350 " dots nor does not start with a dot."
2351 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002352 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002353 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002354 }
2355
2356 err = invalid_domainchar(args[cur_arg + 1]);
2357 if (err) {
2358 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2359 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002362 }
2363
Willy Tarreau68a897b2009-12-03 23:28:34 +01002364 if (!curproxy->cookie_domain) {
2365 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2366 } else {
2367 /* one domain was already specified, add another one by
2368 * building the string which will be returned along with
2369 * the cookie.
2370 */
2371 char *new_ptr;
2372 int new_len = strlen(curproxy->cookie_domain) +
2373 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2374 new_ptr = malloc(new_len);
2375 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2376 free(curproxy->cookie_domain);
2377 curproxy->cookie_domain = new_ptr;
2378 }
Willy Tarreau31936852010-10-06 16:59:56 +02002379 cur_arg++;
2380 }
2381 else if (!strcmp(args[cur_arg], "maxidle")) {
2382 unsigned int maxidle;
2383 const char *res;
2384
2385 if (!*args[cur_arg + 1]) {
2386 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2387 file, linenum, args[cur_arg]);
2388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
2390 }
2391
2392 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2393 if (res) {
2394 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2395 file, linenum, *res, args[cur_arg]);
2396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
2398 }
2399 curproxy->cookie_maxidle = maxidle;
2400 cur_arg++;
2401 }
2402 else if (!strcmp(args[cur_arg], "maxlife")) {
2403 unsigned int maxlife;
2404 const char *res;
2405
2406 if (!*args[cur_arg + 1]) {
2407 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2408 file, linenum, args[cur_arg]);
2409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
2411 }
2412
2413 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2414 if (res) {
2415 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2416 file, linenum, *res, args[cur_arg]);
2417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
2419 }
2420 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002421 cur_arg++;
2422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002424 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 +02002425 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 }
2429 cur_arg++;
2430 }
Willy Tarreau67402132012-05-31 20:40:20 +02002431 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2433 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002434 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 }
2436
Willy Tarreau67402132012-05-31 20:40:20 +02002437 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2439 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002442
Willy Tarreau67402132012-05-31 20:40:20 +02002443 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002444 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2445 file, linenum);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002449 else if (!strcmp(args[0], "persist")) { /* persist */
2450 if (*(args[1]) == 0) {
2451 Alert("parsing [%s:%d] : missing persist method.\n",
2452 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002455 }
2456
2457 if (!strncmp(args[1], "rdp-cookie", 10)) {
2458 curproxy->options2 |= PR_O2_RDPC_PRST;
2459
Emeric Brunb982a3d2010-01-04 15:45:53 +01002460 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002461 const char *beg, *end;
2462
2463 beg = args[1] + 11;
2464 end = strchr(beg, ')');
2465
2466 if (!end || end == beg) {
2467 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2468 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002471 }
2472
2473 free(curproxy->rdp_cookie_name);
2474 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2475 curproxy->rdp_cookie_len = end-beg;
2476 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002477 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002478 free(curproxy->rdp_cookie_name);
2479 curproxy->rdp_cookie_name = strdup("msts");
2480 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2481 }
2482 else { /* syntax */
2483 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2484 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002487 }
2488 }
2489 else {
2490 Alert("parsing [%s:%d] : unknown persist method.\n",
2491 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002494 }
2495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002497 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002499 if (curproxy == &defproxy) {
2500 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
2503 }
2504
Willy Tarreau977b8e42006-12-29 14:19:17 +01002505 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002507
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002509 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002513 }
2514 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002515 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 curproxy->appsession_name = strdup(args[1]);
2517 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2518 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002519 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2520 if (err) {
2521 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2522 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002525 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002526 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002527
Willy Tarreau51041c72007-09-09 21:56:53 +02002528 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2529 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_ABORT;
2531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002533
2534 cur_arg = 6;
2535 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002536 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2537 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002538 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002539 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002540 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002541 } else if (!strcmp(args[cur_arg], "prefix")) {
2542 curproxy->options2 |= PR_O2_AS_PFX;
2543 } else if (!strcmp(args[cur_arg], "mode")) {
2544 if (!*args[cur_arg + 1]) {
2545 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2546 file, linenum, args[0], args[cur_arg]);
2547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
2549 }
2550
2551 cur_arg++;
2552 if (!strcmp(args[cur_arg], "query-string")) {
2553 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2554 curproxy->options2 |= PR_O2_AS_M_QS;
2555 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2556 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2557 curproxy->options2 |= PR_O2_AS_M_PP;
2558 } else {
2559 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
2562 }
2563 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002564 cur_arg++;
2565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 } /* Url App Session */
2567 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002568 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002570
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002572 if (curproxy == &defproxy) {
2573 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
2576 }
2577
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 if (*(args[4]) == 0) {
2579 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2580 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002584 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 curproxy->capture_name = strdup(args[2]);
2586 curproxy->capture_namelen = strlen(curproxy->capture_name);
2587 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 curproxy->to_log |= LW_COOKIE;
2589 }
2590 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2591 struct cap_hdr *hdr;
2592
2593 if (curproxy == &defproxy) {
2594 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 +02002595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 }
2598
2599 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2600 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2601 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 }
2605
2606 hdr = calloc(sizeof(struct cap_hdr), 1);
2607 hdr->next = curproxy->req_cap;
2608 hdr->name = strdup(args[3]);
2609 hdr->namelen = strlen(args[3]);
2610 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002611 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 hdr->index = curproxy->nb_req_cap++;
2613 curproxy->req_cap = hdr;
2614 curproxy->to_log |= LW_REQHDR;
2615 }
2616 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2617 struct cap_hdr *hdr;
2618
2619 if (curproxy == &defproxy) {
2620 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 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 }
2624
2625 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2626 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2627 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 }
2631 hdr = calloc(sizeof(struct cap_hdr), 1);
2632 hdr->next = curproxy->rsp_cap;
2633 hdr->name = strdup(args[3]);
2634 hdr->namelen = strlen(args[3]);
2635 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002636 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637 hdr->index = curproxy->nb_rsp_cap++;
2638 curproxy->rsp_cap = hdr;
2639 curproxy->to_log |= LW_RSPHDR;
2640 }
2641 else {
2642 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2643 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 }
2647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002649 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002651
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 if (*(args[1]) == 0) {
2653 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2654 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 }
2658 curproxy->conn_retries = atol(args[1]);
2659 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002660 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002661 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002662
2663 if (curproxy == &defproxy) {
2664 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2665 err_code |= ERR_ALERT | ERR_FATAL;
2666 goto out;
2667 }
2668
Willy Tarreau20b0de52012-12-24 15:45:22 +01002669 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2670 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2671 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2672 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002673 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002674 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2675 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 +01002676 file, linenum, args[0]);
2677 err_code |= ERR_WARN;
2678 }
2679
Willy Tarreauff011f22011-01-06 17:51:27 +01002680 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002681
Willy Tarreauff011f22011-01-06 17:51:27 +01002682 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002683 err_code |= ERR_ALERT | ERR_ABORT;
2684 goto out;
2685 }
2686
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002687 err_code |= warnif_cond_conflicts(rule->cond,
2688 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2689 file, linenum);
2690
Willy Tarreauff011f22011-01-06 17:51:27 +01002691 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002692 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002693 else if (!strcmp(args[0], "http-response")) { /* response access control */
2694 struct http_res_rule *rule;
2695
2696 if (curproxy == &defproxy) {
2697 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2698 err_code |= ERR_ALERT | ERR_FATAL;
2699 goto out;
2700 }
2701
2702 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2703 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2704 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2705 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2706 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2707 file, linenum, args[0]);
2708 err_code |= ERR_WARN;
2709 }
2710
2711 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2712
2713 if (!rule) {
2714 err_code |= ERR_ALERT | ERR_ABORT;
2715 goto out;
2716 }
2717
2718 err_code |= warnif_cond_conflicts(rule->cond,
2719 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2720 file, linenum);
2721
2722 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2723 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002724 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2725 /* set the header name and length into the proxy structure */
2726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2727 err_code |= ERR_WARN;
2728
2729 if (!*args[1]) {
2730 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2731 file, linenum, args[0]);
2732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
2734 }
2735
2736 /* set the desired header name */
2737 free(curproxy->server_id_hdr_name);
2738 curproxy->server_id_hdr_name = strdup(args[1]);
2739 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2740 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002741 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002742 if (curproxy == &defproxy) {
2743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002746 }
2747
Willy Tarreauef6494c2010-01-28 17:12:36 +01002748 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002749 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2750 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002753 }
2754
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002755 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2756 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2757 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002760 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002761
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002762 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002763 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002764 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002765 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002766 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002767
Cyril Bonté99ed3272010-01-24 23:29:44 +01002768 if (curproxy == &defproxy) {
2769 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
2772 }
2773
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002774 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002775 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2776 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002779 }
2780
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002781 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002782 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002783 err_code |= warnif_cond_conflicts(rule->cond,
2784 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2785 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002786 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002787 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002788 struct switching_rule *rule;
2789
Willy Tarreaub099aca2008-10-12 17:26:37 +02002790 if (curproxy == &defproxy) {
2791 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002794 }
2795
Willy Tarreau55ea7572007-06-17 19:56:27 +02002796 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002797 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002798
2799 if (*(args[1]) == 0) {
2800 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002801 err_code |= ERR_ALERT | ERR_FATAL;
2802 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002803 }
2804
Willy Tarreauef6494c2010-01-28 17:12:36 +01002805 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002806 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2807 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002810 }
2811
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002812 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2813 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2814 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002817 }
2818
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002819 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002820
Willy Tarreau55ea7572007-06-17 19:56:27 +02002821 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2822 rule->cond = cond;
2823 rule->be.name = strdup(args[1]);
2824 LIST_INIT(&rule->list);
2825 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2826 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002827 else if (strcmp(args[0], "use-server") == 0) {
2828 struct server_rule *rule;
2829
2830 if (curproxy == &defproxy) {
2831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
2834 }
2835
2836 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2837 err_code |= ERR_WARN;
2838
2839 if (*(args[1]) == 0) {
2840 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843 }
2844
2845 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2846 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2847 file, linenum, args[0]);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
2851
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002852 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2853 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2854 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
2857 }
2858
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002859 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002860
2861 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2862 rule->cond = cond;
2863 rule->srv.name = strdup(args[1]);
2864 LIST_INIT(&rule->list);
2865 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2866 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2867 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002868 else if ((!strcmp(args[0], "force-persist")) ||
2869 (!strcmp(args[0], "ignore-persist"))) {
2870 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002871
2872 if (curproxy == &defproxy) {
2873 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
2876 }
2877
2878 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2879 err_code |= ERR_WARN;
2880
Willy Tarreauef6494c2010-01-28 17:12:36 +01002881 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002882 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2883 file, linenum, args[0]);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
2887
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002888 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2889 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2890 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
2893 }
2894
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002895 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2896 * where force-persist is applied.
2897 */
2898 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002899
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002900 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002901 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002902 if (!strcmp(args[0], "force-persist")) {
2903 rule->type = PERSIST_TYPE_FORCE;
2904 } else {
2905 rule->type = PERSIST_TYPE_IGNORE;
2906 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002907 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002908 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002909 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002910 else if (!strcmp(args[0], "stick-table")) {
2911 int myidx = 1;
2912
Emeric Brun32da3c42010-09-23 18:39:19 +02002913 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002914 curproxy->table.type = (unsigned int)-1;
2915 while (*args[myidx]) {
2916 const char *err;
2917
2918 if (strcmp(args[myidx], "size") == 0) {
2919 myidx++;
2920 if (!*(args[myidx])) {
2921 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2922 file, linenum, args[myidx-1]);
2923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
2925 }
2926 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2927 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2928 file, linenum, *err, args[myidx-1]);
2929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
2931 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002932 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002933 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002934 else if (strcmp(args[myidx], "peers") == 0) {
2935 myidx++;
Godbach50523162013-12-11 19:48:57 +08002936 if (!*(args[myidx])) {
2937 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2938 file, linenum, args[myidx-1]);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002942 curproxy->table.peers.name = strdup(args[myidx++]);
2943 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002944 else if (strcmp(args[myidx], "expire") == 0) {
2945 myidx++;
2946 if (!*(args[myidx])) {
2947 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2948 file, linenum, args[myidx-1]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2953 if (err) {
2954 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2955 file, linenum, *err, args[myidx-1]);
2956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
2958 }
2959 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002960 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002961 }
2962 else if (strcmp(args[myidx], "nopurge") == 0) {
2963 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002964 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002965 }
2966 else if (strcmp(args[myidx], "type") == 0) {
2967 myidx++;
2968 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2969 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2970 file, linenum, args[myidx]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002974 /* myidx already points to next arg */
2975 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002976 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002977 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002978 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002979
2980 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002981 nw = args[myidx];
2982 while (*nw) {
2983 /* the "store" keyword supports a comma-separated list */
2984 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002985 sa = NULL; /* store arg */
2986 while (*nw && *nw != ',') {
2987 if (*nw == '(') {
2988 *nw = 0;
2989 sa = ++nw;
2990 while (*nw != ')') {
2991 if (!*nw) {
2992 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2993 file, linenum, args[0], cw);
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997 nw++;
2998 }
2999 *nw = '\0';
3000 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003001 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003002 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003003 if (*nw)
3004 *nw++ = '\0';
3005 type = stktable_get_data_type(cw);
3006 if (type < 0) {
3007 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3008 file, linenum, args[0], cw);
3009 err_code |= ERR_ALERT | ERR_FATAL;
3010 goto out;
3011 }
Willy Tarreauac782882010-06-20 10:41:54 +02003012
3013 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3014 switch (err) {
3015 case PE_NONE: break;
3016 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003017 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3018 file, linenum, args[0], cw);
3019 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003020 break;
3021
3022 case PE_ARG_MISSING:
3023 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3024 file, linenum, args[0], cw);
3025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
3027
3028 case PE_ARG_NOT_USED:
3029 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3030 file, linenum, args[0], cw);
3031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
3033
3034 default:
3035 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3036 file, linenum, args[0], cw);
3037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003039 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003040 }
3041 myidx++;
3042 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003043 else {
3044 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3045 file, linenum, args[myidx]);
3046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003049 }
3050
3051 if (!curproxy->table.size) {
3052 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3053 file, linenum);
3054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
3056 }
3057
3058 if (curproxy->table.type == (unsigned int)-1) {
3059 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3060 file, linenum);
3061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
3063 }
3064 }
3065 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003066 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003067 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003068 int myidx = 0;
3069 const char *name = NULL;
3070 int flags;
3071
3072 if (curproxy == &defproxy) {
3073 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
3076 }
3077
3078 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3079 err_code |= ERR_WARN;
3080 goto out;
3081 }
3082
3083 myidx++;
3084 if ((strcmp(args[myidx], "store") == 0) ||
3085 (strcmp(args[myidx], "store-request") == 0)) {
3086 myidx++;
3087 flags = STK_IS_STORE;
3088 }
3089 else if (strcmp(args[myidx], "store-response") == 0) {
3090 myidx++;
3091 flags = STK_IS_STORE | STK_ON_RSP;
3092 }
3093 else if (strcmp(args[myidx], "match") == 0) {
3094 myidx++;
3095 flags = STK_IS_MATCH;
3096 }
3097 else if (strcmp(args[myidx], "on") == 0) {
3098 myidx++;
3099 flags = STK_IS_MATCH | STK_IS_STORE;
3100 }
3101 else {
3102 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
3106
3107 if (*(args[myidx]) == 0) {
3108 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
3111 }
3112
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003113 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003114 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003115 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003116 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
3119 }
3120
3121 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003122 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3123 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3124 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003125 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003126 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003127 goto out;
3128 }
3129 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003130 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3131 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3132 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003133 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003134 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003135 goto out;
3136 }
3137 }
3138
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003139 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003140 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003141
Emeric Brunb982a3d2010-01-04 15:45:53 +01003142 if (strcmp(args[myidx], "table") == 0) {
3143 myidx++;
3144 name = args[myidx++];
3145 }
3146
Willy Tarreauef6494c2010-01-28 17:12:36 +01003147 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003148 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3149 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3150 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003151 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003152 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003153 goto out;
3154 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003155 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003156 else if (*(args[myidx])) {
3157 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3158 file, linenum, args[0], args[myidx]);
3159 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003160 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003161 goto out;
3162 }
Emeric Brun97679e72010-09-23 17:56:44 +02003163 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003164 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003165 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003166 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003167
Emeric Brunb982a3d2010-01-04 15:45:53 +01003168 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3169 rule->cond = cond;
3170 rule->expr = expr;
3171 rule->flags = flags;
3172 rule->table.name = name ? strdup(name) : NULL;
3173 LIST_INIT(&rule->list);
3174 if (flags & STK_ON_RSP)
3175 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3176 else
3177 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3178 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003180 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003182
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3184 curproxy->uri_auth = NULL; /* we must detach from the default config */
3185
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003186 if (!*args[1]) {
3187 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003188 } else if (!strcmp(args[1], "admin")) {
3189 struct stats_admin_rule *rule;
3190
3191 if (curproxy == &defproxy) {
3192 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
3196
3197 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3198 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3199 err_code |= ERR_ALERT | ERR_ABORT;
3200 goto out;
3201 }
3202
3203 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3204 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3205 file, linenum, args[0], args[1]);
3206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003209 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3210 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3211 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
3214 }
3215
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003216 err_code |= warnif_cond_conflicts(cond,
3217 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3218 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003219
3220 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3221 rule->cond = cond;
3222 LIST_INIT(&rule->list);
3223 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 } else if (!strcmp(args[1], "uri")) {
3225 if (*(args[2]) == 0) {
3226 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3230 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003231 err_code |= ERR_ALERT | ERR_ABORT;
3232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 }
3234 } else if (!strcmp(args[1], "realm")) {
3235 if (*(args[2]) == 0) {
3236 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3240 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003241 err_code |= ERR_ALERT | ERR_ABORT;
3242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003244 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003245 unsigned interval;
3246
3247 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3248 if (err) {
3249 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3250 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003253 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3254 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003255 err_code |= ERR_ALERT | ERR_ABORT;
3256 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003257 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003258 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003259 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003260
3261 if (curproxy == &defproxy) {
3262 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3263 err_code |= ERR_ALERT | ERR_FATAL;
3264 goto out;
3265 }
3266
3267 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3268 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3269 err_code |= ERR_ALERT | ERR_ABORT;
3270 goto out;
3271 }
3272
Willy Tarreauff011f22011-01-06 17:51:27 +01003273 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3274 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003275 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3276 file, linenum, args[0]);
3277 err_code |= ERR_WARN;
3278 }
3279
Willy Tarreauff011f22011-01-06 17:51:27 +01003280 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003281
Willy Tarreauff011f22011-01-06 17:51:27 +01003282 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003283 err_code |= ERR_ALERT | ERR_ABORT;
3284 goto out;
3285 }
3286
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003287 err_code |= warnif_cond_conflicts(rule->cond,
3288 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3289 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003290 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003291
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 } else if (!strcmp(args[1], "auth")) {
3293 if (*(args[2]) == 0) {
3294 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3298 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_ABORT;
3300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 }
3302 } else if (!strcmp(args[1], "scope")) {
3303 if (*(args[2]) == 0) {
3304 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3308 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_ALERT | ERR_ABORT;
3310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 }
3312 } else if (!strcmp(args[1], "enable")) {
3313 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3314 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003315 err_code |= ERR_ALERT | ERR_ABORT;
3316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003318 } else if (!strcmp(args[1], "hide-version")) {
3319 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3320 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_ABORT;
3322 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003323 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003324 } else if (!strcmp(args[1], "show-legends")) {
3325 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3326 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3327 err_code |= ERR_ALERT | ERR_ABORT;
3328 goto out;
3329 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003330 } else if (!strcmp(args[1], "show-node")) {
3331
3332 if (*args[2]) {
3333 int i;
3334 char c;
3335
3336 for (i=0; args[2][i]; i++) {
3337 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003338 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3339 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003340 break;
3341 }
3342
3343 if (!i || args[2][i]) {
3344 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3345 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3346 file, linenum, args[0], args[1]);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
3350 }
3351
3352 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3353 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3354 err_code |= ERR_ALERT | ERR_ABORT;
3355 goto out;
3356 }
3357 } else if (!strcmp(args[1], "show-desc")) {
3358 char *desc = NULL;
3359
3360 if (*args[2]) {
3361 int i, len=0;
3362 char *d;
3363
3364 for(i=2; *args[i]; i++)
3365 len += strlen(args[i])+1;
3366
3367 desc = d = (char *)calloc(1, len);
3368
3369 d += sprintf(d, "%s", args[2]);
3370 for(i=3; *args[i]; i++)
3371 d += sprintf(d, " %s", args[i]);
3372 }
3373
3374 if (!*args[2] && !global.desc)
3375 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3376 file, linenum, args[1]);
3377 else {
3378 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3379 free(desc);
3380 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3381 err_code |= ERR_ALERT | ERR_ABORT;
3382 goto out;
3383 }
3384 free(desc);
3385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003387stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003388 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 +01003389 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }
3393 }
3394 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003395 int optnum;
3396
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003397 if (*(args[1]) == '\0') {
3398 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003403
3404 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3405 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003406 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3407 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3408 file, linenum, cfg_opts[optnum].name);
3409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
3411 }
Willy Tarreau93893792009-07-23 13:19:11 +02003412 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3413 err_code |= ERR_WARN;
3414 goto out;
3415 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003416
Willy Tarreau3842f002009-06-14 11:39:52 +02003417 curproxy->no_options &= ~cfg_opts[optnum].val;
3418 curproxy->options &= ~cfg_opts[optnum].val;
3419
3420 switch (kwm) {
3421 case KWM_STD:
3422 curproxy->options |= cfg_opts[optnum].val;
3423 break;
3424 case KWM_NO:
3425 curproxy->no_options |= cfg_opts[optnum].val;
3426 break;
3427 case KWM_DEF: /* already cleared */
3428 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003429 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003430
Willy Tarreau93893792009-07-23 13:19:11 +02003431 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003432 }
3433 }
3434
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003435 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3436 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003437 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3438 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3439 file, linenum, cfg_opts2[optnum].name);
3440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
3442 }
Willy Tarreau93893792009-07-23 13:19:11 +02003443 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3444 err_code |= ERR_WARN;
3445 goto out;
3446 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003447
Willy Tarreau3842f002009-06-14 11:39:52 +02003448 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3449 curproxy->options2 &= ~cfg_opts2[optnum].val;
3450
3451 switch (kwm) {
3452 case KWM_STD:
3453 curproxy->options2 |= cfg_opts2[optnum].val;
3454 break;
3455 case KWM_NO:
3456 curproxy->no_options2 |= cfg_opts2[optnum].val;
3457 break;
3458 case KWM_DEF: /* already cleared */
3459 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003460 }
Willy Tarreau93893792009-07-23 13:19:11 +02003461 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003462 }
3463 }
3464
Willy Tarreau3842f002009-06-14 11:39:52 +02003465 if (kwm != KWM_STD) {
3466 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003467 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003470 }
3471
Emeric Brun3a058f32009-06-30 18:26:00 +02003472 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003473 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003474 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003475 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003476 if (*(args[2]) != '\0') {
3477 if (!strcmp(args[2], "clf")) {
3478 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003479 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003480 } else {
3481 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003484 }
3485 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003486 if (curproxy->conf.logformat_string != default_http_log_format &&
3487 curproxy->conf.logformat_string != default_tcp_log_format &&
3488 curproxy->conf.logformat_string != clf_http_log_format)
3489 free(curproxy->conf.logformat_string);
3490 curproxy->conf.logformat_string = logformat;
3491
3492 free(curproxy->conf.lfs_file);
3493 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3494 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003495 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003496 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003497 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003498 if (curproxy->conf.logformat_string != default_http_log_format &&
3499 curproxy->conf.logformat_string != default_tcp_log_format &&
3500 curproxy->conf.logformat_string != clf_http_log_format)
3501 free(curproxy->conf.logformat_string);
3502 curproxy->conf.logformat_string = default_tcp_log_format;
3503
3504 free(curproxy->conf.lfs_file);
3505 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3506 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003508 else if (!strcmp(args[1], "tcpka")) {
3509 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003510 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003512
3513 if (curproxy->cap & PR_CAP_FE)
3514 curproxy->options |= PR_O_TCP_CLI_KA;
3515 if (curproxy->cap & PR_CAP_BE)
3516 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 }
3518 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003519 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_WARN;
3521
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003523 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003524 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003525 curproxy->options2 &= ~PR_O2_CHK_ANY;
3526 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 if (!*args[2]) { /* no argument */
3528 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3529 curproxy->check_len = strlen(DEF_CHECK_REQ);
3530 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003531 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 curproxy->check_req = (char *)malloc(reqlen);
3533 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003534 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003536 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003537 if (*args[4])
3538 reqlen += strlen(args[4]);
3539 else
3540 reqlen += strlen("HTTP/1.0");
3541
3542 curproxy->check_req = (char *)malloc(reqlen);
3543 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003544 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003546 }
3547 else if (!strcmp(args[1], "ssl-hello-chk")) {
3548 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003549 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003550 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003551
Willy Tarreaua534fea2008-08-03 12:19:50 +02003552 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003553 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003554 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003555 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003556 }
Willy Tarreau23677902007-05-08 23:50:35 +02003557 else if (!strcmp(args[1], "smtpchk")) {
3558 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003559 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003560 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003561 curproxy->options2 &= ~PR_O2_CHK_ANY;
3562 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003563
3564 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3565 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3566 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3567 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3568 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3569 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3570 curproxy->check_req = (char *)malloc(reqlen);
3571 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3572 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3573 } else {
3574 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3575 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3576 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3577 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3578 }
3579 }
3580 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003581 else if (!strcmp(args[1], "pgsql-check")) {
3582 /* use PostgreSQL request to check servers' health */
3583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3584 err_code |= ERR_WARN;
3585
3586 free(curproxy->check_req);
3587 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003588 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003589 curproxy->options2 |= PR_O2_PGSQL_CHK;
3590
3591 if (*(args[2])) {
3592 int cur_arg = 2;
3593
3594 while (*(args[cur_arg])) {
3595 if (strcmp(args[cur_arg], "user") == 0) {
3596 char * packet;
3597 uint32_t packet_len;
3598 uint32_t pv;
3599
3600 /* suboption header - needs additional argument for it */
3601 if (*(args[cur_arg+1]) == 0) {
3602 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3603 file, linenum, args[0], args[1], args[cur_arg]);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606 }
3607
3608 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3609 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3610 pv = htonl(0x30000); /* protocol version 3.0 */
3611
3612 packet = (char*) calloc(1, packet_len);
3613
3614 memcpy(packet + 4, &pv, 4);
3615
3616 /* copy "user" */
3617 memcpy(packet + 8, "user", 4);
3618
3619 /* copy username */
3620 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3621
3622 free(curproxy->check_req);
3623 curproxy->check_req = packet;
3624 curproxy->check_len = packet_len;
3625
3626 packet_len = htonl(packet_len);
3627 memcpy(packet, &packet_len, 4);
3628 cur_arg += 2;
3629 } else {
3630 /* unknown suboption - catchall */
3631 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3632 file, linenum, args[0], args[1]);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636 } /* end while loop */
3637 }
3638 }
3639
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003640 else if (!strcmp(args[1], "redis-check")) {
3641 /* use REDIS PING request to check servers' health */
3642 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3643 err_code |= ERR_WARN;
3644
3645 free(curproxy->check_req);
3646 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003647 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003648 curproxy->options2 |= PR_O2_REDIS_CHK;
3649
3650 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3651 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3652 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3653 }
3654
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003655 else if (!strcmp(args[1], "mysql-check")) {
3656 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3658 err_code |= ERR_WARN;
3659
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003660 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003661 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003662 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003663 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003664
3665 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3666 * const char mysql40_client_auth_pkt[] = {
3667 * "\x0e\x00\x00" // packet length
3668 * "\x01" // packet number
3669 * "\x00\x00" // client capabilities
3670 * "\x00\x00\x01" // max packet
3671 * "haproxy\x00" // username (null terminated string)
3672 * "\x00" // filler (always 0x00)
3673 * "\x01\x00\x00" // packet length
3674 * "\x00" // packet number
3675 * "\x01" // COM_QUIT command
3676 * };
3677 */
3678
3679 if (*(args[2])) {
3680 int cur_arg = 2;
3681
3682 while (*(args[cur_arg])) {
3683 if (strcmp(args[cur_arg], "user") == 0) {
3684 char *mysqluser;
3685 int packetlen, reqlen, userlen;
3686
3687 /* suboption header - needs additional argument for it */
3688 if (*(args[cur_arg+1]) == 0) {
3689 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3690 file, linenum, args[0], args[1], args[cur_arg]);
3691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
3693 }
3694 mysqluser = args[cur_arg + 1];
3695 userlen = strlen(mysqluser);
3696 packetlen = userlen + 7;
3697 reqlen = packetlen + 9;
3698
3699 free(curproxy->check_req);
3700 curproxy->check_req = (char *)calloc(1, reqlen);
3701 curproxy->check_len = reqlen;
3702
3703 snprintf(curproxy->check_req, 4, "%c%c%c",
3704 ((unsigned char) packetlen & 0xff),
3705 ((unsigned char) (packetlen >> 8) & 0xff),
3706 ((unsigned char) (packetlen >> 16) & 0xff));
3707
3708 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003709 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003710 curproxy->check_req[8] = 1;
3711 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3712 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3713 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3714 cur_arg += 2;
3715 } else {
3716 /* unknown suboption - catchall */
3717 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3718 file, linenum, args[0], args[1]);
3719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
3721 }
3722 } /* end while loop */
3723 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003724 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003725 else if (!strcmp(args[1], "ldap-check")) {
3726 /* use LDAP request to check servers' health */
3727 free(curproxy->check_req);
3728 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003729 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003730 curproxy->options2 |= PR_O2_LDAP_CHK;
3731
3732 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3733 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3734 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3735 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003736 else if (!strcmp(args[1], "tcp-check")) {
3737 /* use raw TCPCHK send/expect to check servers' health */
3738 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3739 err_code |= ERR_WARN;
3740
3741 free(curproxy->check_req);
3742 curproxy->check_req = NULL;
3743 curproxy->options2 &= ~PR_O2_CHK_ANY;
3744 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3745 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003746 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003747 int cur_arg;
3748
3749 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3750 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003751 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003752
Willy Tarreau87cf5142011-08-19 22:57:24 +02003753 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003754
3755 free(curproxy->fwdfor_hdr_name);
3756 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3757 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3758
3759 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3760 cur_arg = 2;
3761 while (*(args[cur_arg])) {
3762 if (!strcmp(args[cur_arg], "except")) {
3763 /* suboption except - needs additional argument for it */
3764 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3765 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3766 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003769 }
3770 /* flush useless bits */
3771 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003772 cur_arg += 2;
3773 } else if (!strcmp(args[cur_arg], "header")) {
3774 /* suboption header - needs additional argument for it */
3775 if (*(args[cur_arg+1]) == 0) {
3776 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3777 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003780 }
3781 free(curproxy->fwdfor_hdr_name);
3782 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3783 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3784 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003785 } else if (!strcmp(args[cur_arg], "if-none")) {
3786 curproxy->options &= ~PR_O_FF_ALWAYS;
3787 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003788 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003789 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003790 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003791 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003794 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003795 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003796 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003797 else if (!strcmp(args[1], "originalto")) {
3798 int cur_arg;
3799
3800 /* insert x-original-to field, but not for the IP address listed as an except.
3801 * set default options (ie: bitfield, header name, etc)
3802 */
3803
3804 curproxy->options |= PR_O_ORGTO;
3805
3806 free(curproxy->orgto_hdr_name);
3807 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3808 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3809
Willy Tarreau87cf5142011-08-19 22:57:24 +02003810 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003811 cur_arg = 2;
3812 while (*(args[cur_arg])) {
3813 if (!strcmp(args[cur_arg], "except")) {
3814 /* suboption except - needs additional argument for it */
3815 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3816 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3817 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003820 }
3821 /* flush useless bits */
3822 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3823 cur_arg += 2;
3824 } else if (!strcmp(args[cur_arg], "header")) {
3825 /* suboption header - needs additional argument for it */
3826 if (*(args[cur_arg+1]) == 0) {
3827 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3828 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003831 }
3832 free(curproxy->orgto_hdr_name);
3833 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3834 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3835 cur_arg += 2;
3836 } else {
3837 /* unknown suboption - catchall */
3838 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3839 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003842 }
3843 } /* end while loop */
3844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 else {
3846 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 }
Willy Tarreau93893792009-07-23 13:19:11 +02003850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003852 else if (!strcmp(args[0], "default_backend")) {
3853 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003855
3856 if (*(args[1]) == 0) {
3857 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003860 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003861 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003862 curproxy->defbe.name = strdup(args[1]);
3863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003867
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003868 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3869 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871 /* enable reconnections to dispatch */
3872 curproxy->options |= PR_O_REDISP;
3873 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003874 else if (!strcmp(args[0], "http-check")) {
3875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003877
3878 if (strcmp(args[1], "disable-on-404") == 0) {
3879 /* enable a graceful server shutdown on an HTTP 404 response */
3880 curproxy->options |= PR_O_DISABLE404;
3881 }
Willy Tarreauef781042010-01-27 11:53:01 +01003882 else if (strcmp(args[1], "send-state") == 0) {
3883 /* enable emission of the apparent state of a server in HTTP checks */
3884 curproxy->options2 |= PR_O2_CHK_SNDST;
3885 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003886 else if (strcmp(args[1], "expect") == 0) {
3887 const char *ptr_arg;
3888 int cur_arg;
3889
3890 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3891 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
3895
3896 cur_arg = 2;
3897 /* consider exclamation marks, sole or at the beginning of a word */
3898 while (*(ptr_arg = args[cur_arg])) {
3899 while (*ptr_arg == '!') {
3900 curproxy->options2 ^= PR_O2_EXP_INV;
3901 ptr_arg++;
3902 }
3903 if (*ptr_arg)
3904 break;
3905 cur_arg++;
3906 }
3907 /* now ptr_arg points to the beginning of a word past any possible
3908 * exclamation mark, and cur_arg is the argument which holds this word.
3909 */
3910 if (strcmp(ptr_arg, "status") == 0) {
3911 if (!*(args[cur_arg + 1])) {
3912 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3913 file, linenum, args[0], args[1], ptr_arg);
3914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
3916 }
3917 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003918 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003919 curproxy->expect_str = strdup(args[cur_arg + 1]);
3920 }
3921 else if (strcmp(ptr_arg, "string") == 0) {
3922 if (!*(args[cur_arg + 1])) {
3923 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3924 file, linenum, args[0], args[1], ptr_arg);
3925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
3927 }
3928 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003929 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003930 curproxy->expect_str = strdup(args[cur_arg + 1]);
3931 }
3932 else if (strcmp(ptr_arg, "rstatus") == 0) {
3933 if (!*(args[cur_arg + 1])) {
3934 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3935 file, linenum, args[0], args[1], ptr_arg);
3936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
3938 }
3939 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003940 free(curproxy->expect_str);
3941 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3942 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003943 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3944 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3945 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3946 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
3949 }
3950 }
3951 else if (strcmp(ptr_arg, "rstring") == 0) {
3952 if (!*(args[cur_arg + 1])) {
3953 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3954 file, linenum, args[0], args[1], ptr_arg);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
3958 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003959 free(curproxy->expect_str);
3960 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3961 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003962 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3963 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3964 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3965 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969 }
3970 else {
3971 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3972 file, linenum, args[0], args[1], ptr_arg);
3973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
3975 }
3976 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003977 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003978 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 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003981 }
3982 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003983 else if (!strcmp(args[0], "tcp-check")) {
3984 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3985 err_code |= ERR_WARN;
3986
3987 if (strcmp(args[1], "send") == 0) {
3988 if (! *(args[2]) ) {
3989 /* SEND string expected */
3990 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
3991 file, linenum, args[0], args[1], args[2]);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 } else {
3995 struct tcpcheck_rule *tcpcheck;
3996
3997 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
3998
3999 tcpcheck->action = TCPCHK_ACT_SEND;
4000 tcpcheck->string_len = strlen(args[2]);
4001 tcpcheck->string = strdup(args[2]);
4002 tcpcheck->expect_regex = NULL;
4003
4004 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4005 }
4006 }
4007 else if (strcmp(args[1], "send-binary") == 0) {
4008 if (! *(args[2]) ) {
4009 /* SEND binary string expected */
4010 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4011 file, linenum, args[0], args[1], args[2]);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
4014 } else {
4015 struct tcpcheck_rule *tcpcheck;
4016 char *err = NULL;
4017
4018 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4019
4020 tcpcheck->action = TCPCHK_ACT_SEND;
4021 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4022 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4023 file, linenum, args[0], args[1], args[2], err);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027 tcpcheck->expect_regex = NULL;
4028
4029 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4030 }
4031 }
4032 else if (strcmp(args[1], "expect") == 0) {
4033 const char *ptr_arg;
4034 int cur_arg;
4035 int inverse = 0;
4036
4037 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4038 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041 }
4042
4043 cur_arg = 2;
4044 /* consider exclamation marks, sole or at the beginning of a word */
4045 while (*(ptr_arg = args[cur_arg])) {
4046 while (*ptr_arg == '!') {
4047 inverse = !inverse;
4048 ptr_arg++;
4049 }
4050 if (*ptr_arg)
4051 break;
4052 cur_arg++;
4053 }
4054 /* now ptr_arg points to the beginning of a word past any possible
4055 * exclamation mark, and cur_arg is the argument which holds this word.
4056 */
4057 if (strcmp(ptr_arg, "binary") == 0) {
4058 if (!*(args[cur_arg + 1])) {
4059 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4060 file, linenum, args[0], args[1], ptr_arg);
4061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
4063 }
4064 struct tcpcheck_rule *tcpcheck;
4065 char *err = NULL;
4066
4067 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4068
4069 tcpcheck->action = TCPCHK_ACT_EXPECT;
4070 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4071 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4072 file, linenum, args[0], args[1], args[2], err);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076 tcpcheck->expect_regex = NULL;
4077 tcpcheck->inverse = inverse;
4078
4079 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4080 }
4081 else if (strcmp(ptr_arg, "string") == 0) {
4082 if (!*(args[cur_arg + 1])) {
4083 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4084 file, linenum, args[0], args[1], ptr_arg);
4085 err_code |= ERR_ALERT | ERR_FATAL;
4086 goto out;
4087 }
4088 struct tcpcheck_rule *tcpcheck;
4089
4090 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4091
4092 tcpcheck->action = TCPCHK_ACT_EXPECT;
4093 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4094 tcpcheck->string = strdup(args[cur_arg + 1]);
4095 tcpcheck->expect_regex = NULL;
4096 tcpcheck->inverse = inverse;
4097
4098 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4099 }
4100 else if (strcmp(ptr_arg, "rstring") == 0) {
4101 if (!*(args[cur_arg + 1])) {
4102 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4103 file, linenum, args[0], args[1], ptr_arg);
4104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106 }
4107 struct tcpcheck_rule *tcpcheck;
4108
4109 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4110
4111 tcpcheck->action = TCPCHK_ACT_EXPECT;
4112 tcpcheck->string_len = 0;
4113 tcpcheck->string = NULL;
4114 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4115 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4116 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4117 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120 }
4121 tcpcheck->inverse = inverse;
4122
4123 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4124 }
4125 else {
4126 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4127 file, linenum, args[0], args[1], ptr_arg);
4128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
4130 }
4131 }
4132 else {
4133 Alert("parsing [%s:%d] : '%s' only supports 'send' or 'expect'.\n", file, linenum, args[0]);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136 }
4137 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004138 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004139 if (curproxy == &defproxy) {
4140 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004143 }
4144
Willy Tarreaub80c2302007-11-30 20:51:32 +01004145 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004146 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004147
4148 if (strcmp(args[1], "fail") == 0) {
4149 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004150 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004151 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4152 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004155 }
4156
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004157 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4158 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4159 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004162 }
4163 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4164 }
4165 else {
4166 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004169 }
4170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171#ifdef TPROXY
4172 else if (!strcmp(args[0], "transparent")) {
4173 /* enable transparent proxy connections */
4174 curproxy->options |= PR_O_TRANSP;
4175 }
4176#endif
4177 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004178 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004179 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004180
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 if (*(args[1]) == 0) {
4182 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004185 }
4186 curproxy->maxconn = atol(args[1]);
4187 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004188 else if (!strcmp(args[0], "backlog")) { /* backlog */
4189 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004190 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004191
4192 if (*(args[1]) == 0) {
4193 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004196 }
4197 curproxy->backlog = atol(args[1]);
4198 }
Willy Tarreau86034312006-12-29 00:10:33 +01004199 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004200 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004201 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004202
Willy Tarreau86034312006-12-29 00:10:33 +01004203 if (*(args[1]) == 0) {
4204 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004207 }
4208 curproxy->fullconn = atol(args[1]);
4209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4211 if (*(args[1]) == 0) {
4212 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004216 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4217 if (err) {
4218 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4219 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004222 }
4223 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 }
4225 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004226 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004227 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004228 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004229
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230 if (curproxy == &defproxy) {
4231 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004234 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004235 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004237
Willy Tarreau902636f2013-03-10 19:44:48 +01004238 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004239 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004240 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004241 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004242 goto out;
4243 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004244
4245 proto = protocol_by_family(sk->ss_family);
4246 if (!proto || !proto->connect) {
4247 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4248 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
4251 }
4252
4253 if (port1 != port2) {
4254 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4255 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004259
4260 if (!port1) {
4261 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4262 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004266
Willy Tarreaud5191e72010-02-09 20:50:45 +01004267 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004268 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004269 }
4270 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004272 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004273
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004274 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4275 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004278 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004280 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004281 /**
4282 * The syntax for hash-type config element is
4283 * hash-type {map-based|consistent} [[<algo>] avalanche]
4284 *
4285 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4286 */
4287 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004288
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004289 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4290 err_code |= ERR_WARN;
4291
4292 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004293 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4294 }
4295 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004296 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4297 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004298 else if (strcmp(args[1], "avalanche") == 0) {
4299 Alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
4300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004302 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004303 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004304 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004305 err_code |= ERR_ALERT | ERR_FATAL;
4306 goto out;
4307 }
Bhaskar98634f02013-10-29 23:30:51 -04004308
4309 /* set the hash function to use */
4310 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004311 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004312 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004313
4314 /* if consistent with no argument, then avalanche modifier is also applied */
4315 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4316 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004317 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004318 /* set the hash function */
4319 if (!strcmp(args[2], "sdbm")) {
4320 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4321 }
4322 else if (!strcmp(args[2], "djb2")) {
4323 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004324 } else if (!strcmp(args[2], "wt6")) {
4325 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004326 }
4327 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004328 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
4331 }
4332
4333 /* set the hash modifier */
4334 if (!strcmp(args[3], "avalanche")) {
4335 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4336 }
4337 else if (*args[3]) {
4338 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
4341 }
Bhaskar98634f02013-10-29 23:30:51 -04004342 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004343 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004344 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004346 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004347 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004348
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004349 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004350 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004353 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004354 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004355 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004356
4357 if (!*args[2]) {
4358 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004362 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004363
4364 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004365 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004366 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4367 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004370 }
4371
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004372 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004373 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004374 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004375 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004376
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004377 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4378 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4379 err_code |= ERR_ALERT | ERR_ABORT;
4380 goto out;
4381 }
4382
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004383 /* the servers are linked backwards first */
4384 newsrv->next = curproxy->srv;
4385 curproxy->srv = newsrv;
4386 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004387 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004388 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004390 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004391 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004392 LIST_INIT(&newsrv->pendconns);
4393 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004394 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004395 newsrv->state = SRV_RUNNING; /* early server setup */
4396 newsrv->last_change = now.tv_sec;
4397 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004399 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004400 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004401 * - IP: => port=+0, relative
4402 * - IP:N => port=N, absolute
4403 * - IP:+N => port=+N, relative
4404 * - IP:-N => port=-N, relative
4405 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004406 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004407 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004408 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004409 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004410 goto out;
4411 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004412
4413 proto = protocol_by_family(sk->ss_family);
4414 if (!proto || !proto->connect) {
4415 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4416 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
4419 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004420
4421 if (!port1 || !port2) {
4422 /* no port specified, +offset, -offset */
4423 newsrv->state |= SRV_MAPPORTS;
4424 }
4425 else if (port1 != port2) {
4426 /* port range */
4427 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4428 file, linenum, args[0], args[1], args[2]);
4429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
4431 }
4432 else {
4433 /* used by checks */
4434 realport = port1;
4435 }
4436
Willy Tarreaud5191e72010-02-09 20:50:45 +01004437 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004438 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4439 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004440
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004441 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004442 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4443 file, linenum, newsrv->addr.ss_family, args[2]);
4444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
4446 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004447
Simon Hormand60d6912013-11-25 10:46:36 +09004448 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004449 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004450 newsrv->check.inter = curproxy->defsrv.check.inter;
4451 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4452 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004453 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4454 newsrv->agent.port = curproxy->defsrv.agent.port;
4455 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4456 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4457 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004458 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4459 newsrv->minconn = curproxy->defsrv.minconn;
4460 newsrv->maxconn = curproxy->defsrv.maxconn;
4461 newsrv->slowstart = curproxy->defsrv.slowstart;
4462 newsrv->onerror = curproxy->defsrv.onerror;
4463 newsrv->consecutive_errors_limit
4464 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004465#ifdef OPENSSL
4466 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4467#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004468 newsrv->uweight = newsrv->iweight
4469 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004470
Simon Horman69d29f92013-02-23 15:14:19 +09004471 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004472 newsrv->check.rise = curproxy->defsrv.check.rise;
4473 newsrv->check.fall = curproxy->defsrv.check.fall;
4474 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004475 newsrv->check.server = newsrv;
4476
Simon Hormand60d6912013-11-25 10:46:36 +09004477 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004478 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4479 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4480 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004481 newsrv->agent.server = newsrv;
4482
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004483 cur_arg = 3;
4484 } else {
4485 newsrv = &curproxy->defsrv;
4486 cur_arg = 1;
4487 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004488
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004490 if (!strcmp(args[cur_arg], "agent-check")) {
4491 global.maxsock++;
4492 do_agent = 1;
4493 cur_arg += 1;
4494 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4495 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4496 if (err) {
4497 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4498 file, linenum, *err, newsrv->id);
4499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
4501 }
4502 if (val <= 0) {
4503 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4504 file, linenum, val, args[cur_arg], newsrv->id);
4505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
4507 }
4508 newsrv->agent.inter = val;
4509 cur_arg += 2;
4510 }
4511 else if (!strcmp(args[cur_arg], "agent-port")) {
4512 global.maxsock++;
4513 newsrv->agent.port = atol(args[cur_arg + 1]);
4514 cur_arg += 2;
4515 }
4516 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517 newsrv->cookie = strdup(args[cur_arg + 1]);
4518 newsrv->cklen = strlen(args[cur_arg + 1]);
4519 cur_arg += 2;
4520 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004521 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004522 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4523 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4524 cur_arg += 2;
4525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004527 if (!*args[cur_arg + 1]) {
4528 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4529 file, linenum, args[cur_arg]);
4530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
4532 }
4533
Simon Horman58c32972013-11-25 10:46:38 +09004534 newsrv->check.rise = atol(args[cur_arg + 1]);
4535 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004536 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4537 file, linenum, args[cur_arg]);
4538 err_code |= ERR_ALERT | ERR_FATAL;
4539 goto out;
4540 }
4541
Simon Horman125d0992013-02-24 17:23:38 +09004542 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004543 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 cur_arg += 2;
4545 }
4546 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004547 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004548
4549 if (!*args[cur_arg + 1]) {
4550 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4551 file, linenum, args[cur_arg]);
4552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
4555
Simon Horman58c32972013-11-25 10:46:38 +09004556 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004557 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4558 file, linenum, args[cur_arg]);
4559 err_code |= ERR_ALERT | ERR_FATAL;
4560 goto out;
4561 }
4562
Willy Tarreaubaaee002006-06-26 02:48:02 +02004563 cur_arg += 2;
4564 }
4565 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004566 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4567 if (err) {
4568 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4569 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004570 err_code |= ERR_ALERT | ERR_FATAL;
4571 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004572 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004573 if (val <= 0) {
4574 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4575 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004578 }
Simon Horman66183002013-02-23 10:16:43 +09004579 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 cur_arg += 2;
4581 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004582 else if (!strcmp(args[cur_arg], "fastinter")) {
4583 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4584 if (err) {
4585 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4586 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004589 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004590 if (val <= 0) {
4591 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4592 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004595 }
Simon Horman66183002013-02-23 10:16:43 +09004596 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004597 cur_arg += 2;
4598 }
4599 else if (!strcmp(args[cur_arg], "downinter")) {
4600 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4601 if (err) {
4602 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4603 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004606 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004607 if (val <= 0) {
4608 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4609 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004612 }
Simon Horman66183002013-02-23 10:16:43 +09004613 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004614 cur_arg += 2;
4615 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004616 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004617 struct sockaddr_storage *sk;
4618 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004619 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004620
Willy Tarreau902636f2013-03-10 19:44:48 +01004621 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004622 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004623 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004624 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004625 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004626 goto out;
4627 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004628
4629 proto = protocol_by_family(sk->ss_family);
4630 if (!proto || !proto->connect) {
4631 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004632 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
4635 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004636
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004637 if (port1 != port2) {
4638 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4639 file, linenum, args[cur_arg], args[cur_arg + 1]);
4640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
4642 }
4643
Simon Horman66183002013-02-23 10:16:43 +09004644 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004645 cur_arg += 2;
4646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004648 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649 cur_arg += 2;
4650 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004651 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 newsrv->state |= SRV_BACKUP;
4653 cur_arg ++;
4654 }
Simon Hormanfa461682011-06-25 09:39:49 +09004655 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4656 newsrv->state |= SRV_NON_STICK;
4657 cur_arg ++;
4658 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004659 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4660 newsrv->state |= SRV_SEND_PROXY;
4661 cur_arg ++;
4662 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004663 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4664 newsrv->check.send_proxy = 1;
4665 cur_arg ++;
4666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 else if (!strcmp(args[cur_arg], "weight")) {
4668 int w;
4669 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004670 if (w < 0 || w > SRV_UWGHT_MAX) {
4671 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4672 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004673 err_code |= ERR_ALERT | ERR_FATAL;
4674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004676 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 cur_arg += 2;
4678 }
4679 else if (!strcmp(args[cur_arg], "minconn")) {
4680 newsrv->minconn = atol(args[cur_arg + 1]);
4681 cur_arg += 2;
4682 }
4683 else if (!strcmp(args[cur_arg], "maxconn")) {
4684 newsrv->maxconn = atol(args[cur_arg + 1]);
4685 cur_arg += 2;
4686 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004687 else if (!strcmp(args[cur_arg], "maxqueue")) {
4688 newsrv->maxqueue = atol(args[cur_arg + 1]);
4689 cur_arg += 2;
4690 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004691 else if (!strcmp(args[cur_arg], "slowstart")) {
4692 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004693 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004694 if (err) {
4695 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4696 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004699 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004700 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004701 cur_arg += 2;
4702 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004703 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004704
4705 if (!*args[cur_arg + 1]) {
4706 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4707 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004710 }
4711
4712 newsrv->trackit = strdup(args[cur_arg + 1]);
4713
4714 cur_arg += 2;
4715 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004716 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 global.maxsock++;
4718 do_check = 1;
4719 cur_arg += 1;
4720 }
Willy Tarreau96839092010-03-29 10:02:24 +02004721 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4722 newsrv->state |= SRV_MAINTAIN;
4723 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09004724 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004725 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004726 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004727 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004728 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004729 if (!strcmp(args[cur_arg + 1], "none"))
4730 newsrv->observe = HANA_OBS_NONE;
4731 else if (!strcmp(args[cur_arg + 1], "layer4"))
4732 newsrv->observe = HANA_OBS_LAYER4;
4733 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4734 if (curproxy->mode != PR_MODE_HTTP) {
4735 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4736 file, linenum, args[cur_arg + 1]);
4737 err_code |= ERR_ALERT;
4738 }
4739 newsrv->observe = HANA_OBS_LAYER7;
4740 }
4741 else {
4742 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004743 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004744 file, linenum, args[cur_arg], args[cur_arg + 1]);
4745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
4747 }
4748
4749 cur_arg += 2;
4750 }
4751 else if (!strcmp(args[cur_arg], "on-error")) {
4752 if (!strcmp(args[cur_arg + 1], "fastinter"))
4753 newsrv->onerror = HANA_ONERR_FASTINTER;
4754 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4755 newsrv->onerror = HANA_ONERR_FAILCHK;
4756 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4757 newsrv->onerror = HANA_ONERR_SUDDTH;
4758 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4759 newsrv->onerror = HANA_ONERR_MARKDWN;
4760 else {
4761 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004762 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004763 file, linenum, args[cur_arg], args[cur_arg + 1]);
4764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
4766 }
4767
4768 cur_arg += 2;
4769 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004770 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4771 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4772 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4773 else {
4774 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4775 file, linenum, args[cur_arg], args[cur_arg + 1]);
4776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
4778 }
4779
4780 cur_arg += 2;
4781 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004782 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4783 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4784 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4785 else {
4786 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4787 file, linenum, args[cur_arg], args[cur_arg + 1]);
4788 err_code |= ERR_ALERT | ERR_FATAL;
4789 goto out;
4790 }
4791
4792 cur_arg += 2;
4793 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004794 else if (!strcmp(args[cur_arg], "error-limit")) {
4795 if (!*args[cur_arg + 1]) {
4796 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4797 file, linenum, args[cur_arg]);
4798 err_code |= ERR_ALERT | ERR_FATAL;
4799 goto out;
4800 }
4801
4802 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4803
4804 if (newsrv->consecutive_errors_limit <= 0) {
4805 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4806 file, linenum, args[cur_arg]);
4807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
4809 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004810 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004811 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004812 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004813 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004814 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004815 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004816
Willy Tarreaubaaee002006-06-26 02:48:02 +02004817 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004818 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4819 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004823
Willy Tarreauef9a3602012-12-08 22:29:20 +01004824 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004825 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004826 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004827 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004828 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004829 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004830 goto out;
4831 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004832
4833 proto = protocol_by_family(sk->ss_family);
4834 if (!proto || !proto->connect) {
4835 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4836 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004837 err_code |= ERR_ALERT | ERR_FATAL;
4838 goto out;
4839 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004840
Willy Tarreauef9a3602012-12-08 22:29:20 +01004841 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004842
4843 if (port_low != port_high) {
4844 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004845
4846 if (!port_low || !port_high) {
4847 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4848 file, linenum, args[cur_arg], args[cur_arg + 1]);
4849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 }
4852
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004853 if (port_low <= 0 || port_low > 65535 ||
4854 port_high <= 0 || port_high > 65535 ||
4855 port_low > port_high) {
4856 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4857 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004860 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004861 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4862 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4863 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004864 }
4865
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004867 while (*(args[cur_arg])) {
4868 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004869#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4870#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004871 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004872 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4873 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004874 err_code |= ERR_ALERT | ERR_FATAL;
4875 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004876 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004877#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004878 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004879 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004880 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004881 err_code |= ERR_ALERT | ERR_FATAL;
4882 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004883 }
4884 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004885 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4886 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004887 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004888 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4889 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004890 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4891 char *name, *end;
4892
4893 name = args[cur_arg+1] + 7;
4894 while (isspace(*name))
4895 name++;
4896
4897 end = name;
4898 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4899 end++;
4900
Willy Tarreauef9a3602012-12-08 22:29:20 +01004901 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4902 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4903 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4904 newsrv->conn_src.bind_hdr_len = end - name;
4905 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4906 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4907 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004908
4909 /* now look for an occurrence number */
4910 while (isspace(*end))
4911 end++;
4912 if (*end == ',') {
4913 end++;
4914 name = end;
4915 if (*end == '-')
4916 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004917 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004918 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004919 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004920 }
4921
Willy Tarreauef9a3602012-12-08 22:29:20 +01004922 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004923 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4924 " occurrences values smaller than %d.\n",
4925 file, linenum, MAX_HDR_HISTORY);
4926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
4928 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004929 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004930 struct sockaddr_storage *sk;
4931 int port1, port2;
4932
Willy Tarreau902636f2013-03-10 19:44:48 +01004933 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004934 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004935 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004936 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004937 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004938 goto out;
4939 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004940
4941 proto = protocol_by_family(sk->ss_family);
4942 if (!proto || !proto->connect) {
4943 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4944 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
4947 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004948
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004949 if (port1 != port2) {
4950 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4951 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004952 err_code |= ERR_ALERT | ERR_FATAL;
4953 goto out;
4954 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004955 newsrv->conn_src.tproxy_addr = *sk;
4956 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004957 }
4958 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004959#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004960 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004961#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004962 cur_arg += 2;
4963 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004964#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004965 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004966 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004967 err_code |= ERR_ALERT | ERR_FATAL;
4968 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004969#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004970 } /* "usesrc" */
4971
4972 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4973#ifdef SO_BINDTODEVICE
4974 if (!*args[cur_arg + 1]) {
4975 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4976 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004977 err_code |= ERR_ALERT | ERR_FATAL;
4978 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004979 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004980 free(newsrv->conn_src.iface_name);
4981 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4982 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004983 global.last_checks |= LSTCHK_NETADM;
4984#else
4985 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4986 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004989#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004990 cur_arg += 2;
4991 continue;
4992 }
4993 /* this keyword in not an option of "source" */
4994 break;
4995 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004997 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004998 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4999 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005000 err_code |= ERR_ALERT | ERR_FATAL;
5001 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005004 static int srv_dumped;
5005 struct srv_kw *kw;
5006 char *err;
5007
5008 kw = srv_find_kw(args[cur_arg]);
5009 if (kw) {
5010 char *err = NULL;
5011 int code;
5012
5013 if (!kw->parse) {
5014 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5015 file, linenum, args[0], args[1], args[cur_arg]);
5016 cur_arg += 1 + kw->skip ;
5017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
5019 }
5020
5021 if (defsrv && !kw->default_ok) {
5022 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5023 file, linenum, args[0], args[1], args[cur_arg]);
5024 cur_arg += 1 + kw->skip ;
5025 err_code |= ERR_ALERT;
5026 continue;
5027 }
5028
5029 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5030 err_code |= code;
5031
5032 if (code) {
5033 if (err && *err) {
5034 indent_msg(&err, 2);
5035 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5036 }
5037 else
5038 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5039 file, linenum, args[0], args[1], args[cur_arg]);
5040 if (code & ERR_FATAL) {
5041 free(err);
5042 cur_arg += 1 + kw->skip;
5043 goto out;
5044 }
5045 }
5046 free(err);
5047 cur_arg += 1 + kw->skip;
5048 continue;
5049 }
5050
5051 err = NULL;
5052 if (!srv_dumped) {
5053 srv_dump_kws(&err);
5054 indent_msg(&err, 4);
5055 srv_dumped = 1;
5056 }
5057
5058 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5059 file, linenum, args[0], args[1], args[cur_arg],
5060 err ? " Registered keywords :" : "", err ? err : "");
5061 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005062
Willy Tarreau93893792009-07-23 13:19:11 +02005063 err_code |= ERR_ALERT | ERR_FATAL;
5064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005065 }
5066 }
5067
Simon Horman8c3d0be2013-11-25 10:46:40 +09005068 /* Set initial drain state using now-configured weight */
5069 set_server_drain_state(newsrv);
5070
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005072 int ret;
5073
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005074 if (newsrv->trackit) {
5075 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5076 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_ALERT | ERR_FATAL;
5078 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005079 }
5080
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005081 /* If neither a port nor an addr was specified and no check transport
5082 * layer is forced, then the transport layer used by the checks is the
5083 * same as for the production traffic. Otherwise we use raw_sock by
5084 * default, unless one is specified.
5085 */
Simon Horman66183002013-02-23 10:16:43 +09005086 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005087#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005088 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02005089#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005090 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5091 }
Simon Horman66183002013-02-23 10:16:43 +09005092 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005093 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005094 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005095
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005096 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005097 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005098
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005099 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005100 /* not yet valid, because no port was set on
5101 * the server either. We'll check if we have
5102 * a known port on the first listener.
5103 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005104 struct listener *l;
5105
5106 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005107 newsrv->check.port = get_host_port(&l->addr);
5108 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005109 break;
5110 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005111 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005112 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5114 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005117 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005118
Willy Tarreau2f075e92013-12-03 11:11:34 +01005119 /* note: check type will be set during the config review phase */
5120 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005121 if (ret) {
5122 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005123 goto out;
5124 }
5125
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 newsrv->state |= SRV_CHECKED;
5127 }
5128
Simon Hormand60d6912013-11-25 10:46:36 +09005129 if (do_agent) {
5130 int ret;
5131
5132 if (!newsrv->agent.port) {
5133 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5134 file, linenum, newsrv->id);
5135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
5137 }
5138
5139 if (!newsrv->agent.inter)
5140 newsrv->agent.inter = newsrv->check.inter;
5141
5142 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5143 if (ret) {
5144 err_code |= ret;
5145 goto out;
5146 }
5147
5148 newsrv->state |= SRV_AGENT_CHECKED;
5149 }
5150
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005151 if (!defsrv) {
5152 if (newsrv->state & SRV_BACKUP)
5153 curproxy->srv_bck++;
5154 else
5155 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005156
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005157 newsrv->prev_state = newsrv->state;
5158 }
William Lallemanda73203e2012-03-12 12:48:57 +01005159 }
5160
5161 else if (strcmp(args[0], "unique-id-format") == 0) {
5162 if (!*(args[1])) {
5163 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
5166 }
William Lallemand3203ff42012-11-11 17:30:56 +01005167 if (*(args[2])) {
5168 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
5171 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005172 free(curproxy->conf.uniqueid_format_string);
5173 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005174
Willy Tarreau62a61232013-04-12 18:13:46 +02005175 free(curproxy->conf.uif_file);
5176 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5177 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005178 }
William Lallemanda73203e2012-03-12 12:48:57 +01005179
5180 else if (strcmp(args[0], "unique-id-header") == 0) {
5181 if (!*(args[1])) {
5182 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
5186 free(curproxy->header_unique_id);
5187 curproxy->header_unique_id = strdup(args[1]);
5188 }
5189
William Lallemand723b73a2012-02-08 16:37:49 +01005190 else if (strcmp(args[0], "log-format") == 0) {
5191 if (!*(args[1])) {
5192 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5193 err_code |= ERR_ALERT | ERR_FATAL;
5194 goto out;
5195 }
William Lallemand3203ff42012-11-11 17:30:56 +01005196 if (*(args[2])) {
5197 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5198 err_code |= ERR_ALERT | ERR_FATAL;
5199 goto out;
5200 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005201
Willy Tarreau62a61232013-04-12 18:13:46 +02005202 if (curproxy->conf.logformat_string != default_http_log_format &&
5203 curproxy->conf.logformat_string != default_tcp_log_format &&
5204 curproxy->conf.logformat_string != clf_http_log_format)
5205 free(curproxy->conf.logformat_string);
5206 curproxy->conf.logformat_string = strdup(args[1]);
5207
5208 free(curproxy->conf.lfs_file);
5209 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5210 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005211
5212 /* get a chance to improve log-format error reporting by
5213 * reporting the correct line-number when possible.
5214 */
5215 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5216 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5217 file, linenum, curproxy->id);
5218 err_code |= ERR_WARN;
5219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 }
William Lallemand723b73a2012-02-08 16:37:49 +01005221
William Lallemand0f99e342011-10-12 17:50:54 +02005222 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5223 /* delete previous herited or defined syslog servers */
5224 struct logsrv *back;
5225
5226 if (*(args[1]) != 0) {
5227 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5228 err_code |= ERR_ALERT | ERR_FATAL;
5229 goto out;
5230 }
5231
William Lallemand723b73a2012-02-08 16:37:49 +01005232 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5233 LIST_DEL(&tmplogsrv->list);
5234 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005235 }
5236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005238 struct logsrv *logsrv;
5239
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005241 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005242 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005243 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005244 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005245 LIST_INIT(&node->list);
5246 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 }
5249 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005250 struct sockaddr_storage *sk;
5251 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005252
5253 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254
William Lallemand0f99e342011-10-12 17:50:54 +02005255 logsrv->facility = get_log_facility(args[2]);
5256 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005258 err_code |= ERR_ALERT | ERR_FATAL;
5259 goto out;
5260
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 }
5262
William Lallemand0f99e342011-10-12 17:50:54 +02005263 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005265 logsrv->level = get_log_level(args[3]);
5266 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005267 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 }
5272 }
5273
William Lallemand0f99e342011-10-12 17:50:54 +02005274 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005275 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005276 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005277 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005278 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005279 err_code |= ERR_ALERT | ERR_FATAL;
5280 goto out;
5281
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005282 }
5283 }
5284
Willy Tarreau902636f2013-03-10 19:44:48 +01005285 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005286 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005287 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005288 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005289 goto out;
5290 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005291
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005292 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005293
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005294 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005295 if (port1 != port2) {
5296 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5297 file, linenum, args[0], args[1]);
5298 err_code |= ERR_ALERT | ERR_FATAL;
5299 goto out;
5300 }
5301
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005302 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005303 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 }
William Lallemand0f99e342011-10-12 17:50:54 +02005305
5306 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307 }
5308 else {
5309 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5310 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005311 err_code |= ERR_ALERT | ERR_FATAL;
5312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 }
5314 }
5315 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005316 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005317 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005318 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005319 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005320
Willy Tarreau977b8e42006-12-29 14:19:17 +01005321 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005322 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005323
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005325 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5326 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005327 err_code |= ERR_ALERT | ERR_FATAL;
5328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005330
5331 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005332 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5333 free(curproxy->conn_src.iface_name);
5334 curproxy->conn_src.iface_name = NULL;
5335 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005336
Willy Tarreau902636f2013-03-10 19:44:48 +01005337 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005338 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005339 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005340 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005341 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005342 goto out;
5343 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005344
5345 proto = protocol_by_family(sk->ss_family);
5346 if (!proto || !proto->connect) {
5347 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005348 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
5351 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005352
5353 if (port1 != port2) {
5354 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5355 file, linenum, args[0], args[1]);
5356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
5358 }
5359
Willy Tarreauef9a3602012-12-08 22:29:20 +01005360 curproxy->conn_src.source_addr = *sk;
5361 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005362
5363 cur_arg = 2;
5364 while (*(args[cur_arg])) {
5365 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005366#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5367#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005368 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005369 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5370 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005371 err_code |= ERR_ALERT | ERR_FATAL;
5372 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005373 }
5374#endif
5375 if (!*args[cur_arg + 1]) {
5376 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5377 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005380 }
5381
5382 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005383 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5384 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005385 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005386 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5387 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005388 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5389 char *name, *end;
5390
5391 name = args[cur_arg+1] + 7;
5392 while (isspace(*name))
5393 name++;
5394
5395 end = name;
5396 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5397 end++;
5398
Willy Tarreauef9a3602012-12-08 22:29:20 +01005399 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5400 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5401 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5402 curproxy->conn_src.bind_hdr_len = end - name;
5403 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5404 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5405 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005406
5407 /* now look for an occurrence number */
5408 while (isspace(*end))
5409 end++;
5410 if (*end == ',') {
5411 end++;
5412 name = end;
5413 if (*end == '-')
5414 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005415 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005416 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005417 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005418 }
5419
Willy Tarreauef9a3602012-12-08 22:29:20 +01005420 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005421 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5422 " occurrences values smaller than %d.\n",
5423 file, linenum, MAX_HDR_HISTORY);
5424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
5426 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005427 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005428 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005429
Willy Tarreau902636f2013-03-10 19:44:48 +01005430 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005431 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005432 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005433 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005434 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005435 goto out;
5436 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005437
5438 proto = protocol_by_family(sk->ss_family);
5439 if (!proto || !proto->connect) {
5440 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5441 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
5444 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005445
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005446 if (port1 != port2) {
5447 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5448 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
5451 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005452 curproxy->conn_src.tproxy_addr = *sk;
5453 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005454 }
5455 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005456#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005457 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005458#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005459#else /* no TPROXY support */
5460 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005461 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005464#endif
5465 cur_arg += 2;
5466 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005467 }
5468
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005469 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5470#ifdef SO_BINDTODEVICE
5471 if (!*args[cur_arg + 1]) {
5472 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5473 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005474 err_code |= ERR_ALERT | ERR_FATAL;
5475 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005476 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005477 free(curproxy->conn_src.iface_name);
5478 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5479 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005480 global.last_checks |= LSTCHK_NETADM;
5481#else
5482 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5483 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005486#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005487 cur_arg += 2;
5488 continue;
5489 }
5490 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005491 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005496 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5497 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5498 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005499 err_code |= ERR_ALERT | ERR_FATAL;
5500 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005502 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005503 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005504 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5505 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005506 err_code |= ERR_ALERT | ERR_FATAL;
5507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005508 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005509
5510 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005511 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005512 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005513 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005515 }
5516 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005517 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005518 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005519 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005520 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 }
5523 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005524 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005525 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005526 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005527 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529 }
5530 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005531 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005532 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005533 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005534 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536 }
5537 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005538 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005539 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005540 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005541 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005544 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005545 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005546 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005547 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005548 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005549 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005550 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005551 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005552 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005553 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005554 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005555 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005556 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005557 }
5558 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005559 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005560 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005561 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005562 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005563 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005565 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005566 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005567 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5568 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005569 err_code |= ERR_ALERT | ERR_FATAL;
5570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005571 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005572
5573 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005574 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005575 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005576 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578 }
5579 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005580 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005581 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005582 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005583 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585 }
5586 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005587 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005588 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005589 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005590 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 }
5593 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005594 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005595 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005596 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005597 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 }
5600 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005601 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005602 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005603 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005604 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005607 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005608 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005609 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005610 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005611 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005612 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005614 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005615 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005616
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 if (curproxy == &defproxy) {
5618 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005622 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005623 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625 if (*(args[1]) == 0) {
5626 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005629 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005630
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005631 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005632 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5633 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5634 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005635 err_code |= ERR_ALERT | ERR_FATAL;
5636 goto out;
5637 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005638 err_code |= warnif_cond_conflicts(cond,
5639 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5640 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005641 }
5642 else if (*args[2]) {
5643 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5644 file, linenum, args[0], args[2]);
5645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
5647 }
5648
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005649 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005650 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005651 wl->s = strdup(args[1]);
5652 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005653 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005654 }
5655 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005656 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005657 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5658 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005659 err_code |= ERR_ALERT | ERR_FATAL;
5660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005662
Willy Tarreauade5ec42010-01-28 19:33:49 +01005663 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005664 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005665 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005666 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 }
5669 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005670 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005671 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005672 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005673 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 }
5676 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005677 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005678 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005679 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005680 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005682 }
5683 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005684 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5686 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 }
5690
Willy Tarreauade5ec42010-01-28 19:33:49 +01005691 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005692 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005693 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005694 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005696 }
5697 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005698 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005699 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005700 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005701 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 }
5704 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005705 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005706 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005707 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005708 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 }
5711 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005712 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005713
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714 if (curproxy == &defproxy) {
5715 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005719 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005720 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005721
Willy Tarreaubaaee002006-06-26 02:48:02 +02005722 if (*(args[1]) == 0) {
5723 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005724 err_code |= ERR_ALERT | ERR_FATAL;
5725 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 }
5727
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005728 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005729 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5730 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5731 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005732 err_code |= ERR_ALERT | ERR_FATAL;
5733 goto out;
5734 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005735 err_code |= warnif_cond_conflicts(cond,
5736 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5737 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005738 }
5739 else if (*args[2]) {
5740 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5741 file, linenum, args[0], args[2]);
5742 err_code |= ERR_ALERT | ERR_FATAL;
5743 goto out;
5744 }
5745
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005746 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005747 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005748 wl->s = strdup(args[1]);
5749 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 }
5751 else if (!strcmp(args[0], "errorloc") ||
5752 !strcmp(args[0], "errorloc302") ||
5753 !strcmp(args[0], "errorloc303")) { /* error location */
5754 int errnum, errlen;
5755 char *err;
5756
Willy Tarreau977b8e42006-12-29 14:19:17 +01005757 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005758 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005759
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005761 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 }
5765
5766 errnum = atol(args[1]);
5767 if (!strcmp(args[0], "errorloc303")) {
5768 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5769 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5770 } else {
5771 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5772 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5773 }
5774
Willy Tarreau0f772532006-12-23 20:51:41 +01005775 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5776 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005777 chunk_destroy(&curproxy->errmsg[rc]);
5778 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005779 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005781 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005782
5783 if (rc >= HTTP_ERR_SIZE) {
5784 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5785 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 free(err);
5787 }
5788 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005789 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5790 int errnum, errlen, fd;
5791 char *err;
5792 struct stat stat;
5793
5794 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005795 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005796
5797 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005798 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005799 err_code |= ERR_ALERT | ERR_FATAL;
5800 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005801 }
5802
5803 fd = open(args[2], O_RDONLY);
5804 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5805 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5806 file, linenum, args[2], args[1]);
5807 if (fd >= 0)
5808 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005809 err_code |= ERR_ALERT | ERR_FATAL;
5810 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005811 }
5812
Willy Tarreau27a674e2009-08-17 07:23:33 +02005813 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005814 errlen = stat.st_size;
5815 } else {
5816 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005817 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005818 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005819 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005820 }
5821
5822 err = malloc(errlen); /* malloc() must succeed during parsing */
5823 errnum = read(fd, err, errlen);
5824 if (errnum != errlen) {
5825 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5826 file, linenum, args[2], args[1]);
5827 close(fd);
5828 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005829 err_code |= ERR_ALERT | ERR_FATAL;
5830 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005831 }
5832 close(fd);
5833
5834 errnum = atol(args[1]);
5835 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5836 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005837 chunk_destroy(&curproxy->errmsg[rc]);
5838 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005839 break;
5840 }
5841 }
5842
5843 if (rc >= HTTP_ERR_SIZE) {
5844 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5845 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005846 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005847 free(err);
5848 }
5849 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005850 else if (!strcmp(args[0], "compression")) {
5851 struct comp *comp;
5852 if (curproxy->comp == NULL) {
5853 comp = calloc(1, sizeof(struct comp));
5854 curproxy->comp = comp;
5855 } else {
5856 comp = curproxy->comp;
5857 }
5858
5859 if (!strcmp(args[1], "algo")) {
5860 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005861 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005862
William Lallemand82fe75c2012-10-23 10:25:10 +02005863 cur_arg = 2;
5864 if (!*args[cur_arg]) {
5865 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5866 file, linenum, args[0]);
5867 err_code |= ERR_ALERT | ERR_FATAL;
5868 goto out;
5869 }
5870 while (*(args[cur_arg])) {
5871 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5872 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5873 file, linenum, args[0], args[cur_arg]);
5874 err_code |= ERR_ALERT | ERR_FATAL;
5875 goto out;
5876 }
William Lallemand552df672012-11-07 13:21:47 +01005877 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5878 curproxy->comp->algos->end(&ctx);
5879 } else {
5880 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5881 file, linenum, args[0], args[cur_arg]);
5882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
5884 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005885 cur_arg ++;
5886 continue;
5887 }
5888 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005889 else if (!strcmp(args[1], "offload")) {
5890 comp->offload = 1;
5891 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005892 else if (!strcmp(args[1], "type")) {
5893 int cur_arg;
5894 cur_arg = 2;
5895 if (!*args[cur_arg]) {
5896 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5897 file, linenum, args[0]);
5898 err_code |= ERR_ALERT | ERR_FATAL;
5899 goto out;
5900 }
5901 while (*(args[cur_arg])) {
5902 comp_append_type(comp, args[cur_arg]);
5903 cur_arg ++;
5904 continue;
5905 }
5906 }
5907 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005908 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005909 file, linenum, args[0]);
5910 err_code |= ERR_ALERT | ERR_FATAL;
5911 goto out;
5912 }
5913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005915 struct cfg_kw_list *kwl;
5916 int index;
5917
5918 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5919 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5920 if (kwl->kw[index].section != CFG_LISTEN)
5921 continue;
5922 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5923 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005924 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005925 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005926 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005927 err_code |= ERR_ALERT | ERR_FATAL;
5928 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005929 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005930 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005931 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005932 err_code |= ERR_WARN;
5933 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005934 }
Willy Tarreau93893792009-07-23 13:19:11 +02005935 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005936 }
5937 }
5938 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005939
Willy Tarreau6daf3432008-01-22 16:44:08 +01005940 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005941 err_code |= ERR_ALERT | ERR_FATAL;
5942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005943 }
Willy Tarreau93893792009-07-23 13:19:11 +02005944 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005945 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005946 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947}
5948
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005949int
5950cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5951{
5952
5953 int err_code = 0;
5954 const char *err;
5955
5956 if (!strcmp(args[0], "userlist")) { /* new userlist */
5957 struct userlist *newul;
5958
5959 if (!*args[1]) {
5960 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5961 file, linenum, args[0]);
5962 err_code |= ERR_ALERT | ERR_FATAL;
5963 goto out;
5964 }
5965
5966 err = invalid_char(args[1]);
5967 if (err) {
5968 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5969 file, linenum, *err, args[0], args[1]);
5970 err_code |= ERR_ALERT | ERR_FATAL;
5971 goto out;
5972 }
5973
5974 for (newul = userlist; newul; newul = newul->next)
5975 if (!strcmp(newul->name, args[1])) {
5976 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5977 file, linenum, args[1]);
5978 err_code |= ERR_WARN;
5979 goto out;
5980 }
5981
5982 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5983 if (!newul) {
5984 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5985 err_code |= ERR_ALERT | ERR_ABORT;
5986 goto out;
5987 }
5988
5989 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5990 newul->name = strdup(args[1]);
5991
5992 if (!newul->groupusers | !newul->name) {
5993 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5994 err_code |= ERR_ALERT | ERR_ABORT;
5995 goto out;
5996 }
5997
5998 newul->next = userlist;
5999 userlist = newul;
6000
6001 } else if (!strcmp(args[0], "group")) { /* new group */
6002 int cur_arg, i;
6003 const char *err;
6004
6005 if (!*args[1]) {
6006 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6007 file, linenum, args[0]);
6008 err_code |= ERR_ALERT | ERR_FATAL;
6009 goto out;
6010 }
6011
6012 err = invalid_char(args[1]);
6013 if (err) {
6014 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6015 file, linenum, *err, args[0], args[1]);
6016 err_code |= ERR_ALERT | ERR_FATAL;
6017 goto out;
6018 }
6019
6020 for(i = 0; i < userlist->grpcnt; i++)
6021 if (!strcmp(userlist->groups[i], args[1])) {
6022 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6023 file, linenum, args[1], userlist->name);
6024 err_code |= ERR_ALERT;
6025 goto out;
6026 }
6027
6028 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6029 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6030 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6031 err_code |= ERR_ALERT | ERR_FATAL;
6032 goto out;
6033 }
6034
6035 cur_arg = 2;
6036
6037 while (*args[cur_arg]) {
6038 if (!strcmp(args[cur_arg], "users")) {
6039 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6040 cur_arg += 2;
6041 continue;
6042 } else {
6043 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6044 file, linenum, args[0]);
6045 err_code |= ERR_ALERT | ERR_FATAL;
6046 goto out;
6047 }
6048 }
6049
6050 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6051 } else if (!strcmp(args[0], "user")) { /* new user */
6052 struct auth_users *newuser;
6053 int cur_arg;
6054
6055 if (!*args[1]) {
6056 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6057 file, linenum, args[0]);
6058 err_code |= ERR_ALERT | ERR_FATAL;
6059 goto out;
6060 }
6061
6062 for (newuser = userlist->users; newuser; newuser = newuser->next)
6063 if (!strcmp(newuser->user, args[1])) {
6064 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6065 file, linenum, args[1], userlist->name);
6066 err_code |= ERR_ALERT;
6067 goto out;
6068 }
6069
6070 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6071 if (!newuser) {
6072 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6073 err_code |= ERR_ALERT | ERR_ABORT;
6074 goto out;
6075 }
6076
6077 newuser->user = strdup(args[1]);
6078
6079 newuser->next = userlist->users;
6080 userlist->users = newuser;
6081
6082 cur_arg = 2;
6083
6084 while (*args[cur_arg]) {
6085 if (!strcmp(args[cur_arg], "password")) {
6086#ifndef CONFIG_HAP_CRYPT
6087 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6088 file, linenum);
6089 err_code |= ERR_ALERT;
6090#endif
6091 newuser->pass = strdup(args[cur_arg + 1]);
6092 cur_arg += 2;
6093 continue;
6094 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6095 newuser->pass = strdup(args[cur_arg + 1]);
6096 newuser->flags |= AU_O_INSECURE;
6097 cur_arg += 2;
6098 continue;
6099 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006100 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006101 cur_arg += 2;
6102 continue;
6103 } else {
6104 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6105 file, linenum, args[0]);
6106 err_code |= ERR_ALERT | ERR_FATAL;
6107 goto out;
6108 }
6109 }
6110 } else {
6111 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6112 err_code |= ERR_ALERT | ERR_FATAL;
6113 }
6114
6115out:
6116 return err_code;
6117}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006118
6119/*
6120 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006121 * Returns the error code, 0 if OK, or any combination of :
6122 * - ERR_ABORT: must abort ASAP
6123 * - ERR_FATAL: we can continue parsing but not start the service
6124 * - ERR_WARN: a warning has been emitted
6125 * - ERR_ALERT: an alert has been emitted
6126 * Only the two first ones can stop processing, the two others are just
6127 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006128 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006129int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006130{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006131 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006132 FILE *f;
6133 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006135 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006136
Willy Tarreaubaaee002006-06-26 02:48:02 +02006137 if ((f=fopen(file,"r")) == NULL)
6138 return -1;
6139
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006140 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006141 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006142 char *end;
6143 char *args[MAX_LINE_ARGS + 1];
6144 char *line = thisline;
6145
Willy Tarreaubaaee002006-06-26 02:48:02 +02006146 linenum++;
6147
6148 end = line + strlen(line);
6149
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006150 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6151 /* Check if we reached the limit and the last char is not \n.
6152 * Watch out for the last line without the terminating '\n'!
6153 */
6154 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006155 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006156 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006157 }
6158
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006160 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 line++;
6162
6163 arg = 0;
6164 args[arg] = line;
6165
6166 while (*line && arg < MAX_LINE_ARGS) {
6167 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6168 * C equivalent value. Other combinations left unchanged (eg: \1).
6169 */
6170 if (*line == '\\') {
6171 int skip = 0;
6172 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6173 *line = line[1];
6174 skip = 1;
6175 }
6176 else if (line[1] == 'r') {
6177 *line = '\r';
6178 skip = 1;
6179 }
6180 else if (line[1] == 'n') {
6181 *line = '\n';
6182 skip = 1;
6183 }
6184 else if (line[1] == 't') {
6185 *line = '\t';
6186 skip = 1;
6187 }
6188 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006189 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 unsigned char hex1, hex2;
6191 hex1 = toupper(line[2]) - '0';
6192 hex2 = toupper(line[3]) - '0';
6193 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6194 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6195 *line = (hex1<<4) + hex2;
6196 skip = 3;
6197 }
6198 else {
6199 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006200 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 }
6202 }
6203 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006204 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006205 end -= skip;
6206 }
6207 line++;
6208 }
6209 else if (*line == '#' || *line == '\n' || *line == '\r') {
6210 /* end of string, end of loop */
6211 *line = 0;
6212 break;
6213 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006214 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006215 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006216 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006217 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006218 line++;
6219 args[++arg] = line;
6220 }
6221 else {
6222 line++;
6223 }
6224 }
6225
6226 /* empty line */
6227 if (!**args)
6228 continue;
6229
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006230 if (*line) {
6231 /* we had to stop due to too many args.
6232 * Let's terminate the string, print the offending part then cut the
6233 * last arg.
6234 */
6235 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6236 line++;
6237 *line = '\0';
6238
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006239 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006240 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006241 err_code |= ERR_ALERT | ERR_FATAL;
6242 args[arg] = line;
6243 }
6244
Willy Tarreau540abe42007-05-02 20:50:16 +02006245 /* zero out remaining args and ensure that at least one entry
6246 * is zeroed out.
6247 */
6248 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006249 args[arg] = line;
6250 }
6251
Willy Tarreau3842f002009-06-14 11:39:52 +02006252 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006253 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006254 char *tmp;
6255
Willy Tarreau3842f002009-06-14 11:39:52 +02006256 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006257 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006258 for (arg=0; *args[arg+1]; arg++)
6259 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006260 *tmp = '\0'; // fix the next arg to \0
6261 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006262 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006263 else if (!strcmp(args[0], "default")) {
6264 kwm = KWM_DEF;
6265 for (arg=0; *args[arg+1]; arg++)
6266 args[arg] = args[arg+1]; // shift args after inversion
6267 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006268
William Lallemand0f99e342011-10-12 17:50:54 +02006269 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6270 strcmp(args[0], "log") != 0) {
6271 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006272 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006273 }
6274
Willy Tarreau977b8e42006-12-29 14:19:17 +01006275 if (!strcmp(args[0], "listen") ||
6276 !strcmp(args[0], "frontend") ||
6277 !strcmp(args[0], "backend") ||
6278 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006279 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006280 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006281 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006282 cursection = strdup(args[0]);
6283 }
6284 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006285 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006286 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006287 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006288 }
6289 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006290 confsect = CFG_USERLIST;
6291 free(cursection);
6292 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006293 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006294 else if (!strcmp(args[0], "peers")) {
6295 confsect = CFG_PEERS;
6296 free(cursection);
6297 cursection = strdup(args[0]);
6298 }
6299
Willy Tarreaubaaee002006-06-26 02:48:02 +02006300 /* else it's a section keyword */
6301
6302 switch (confsect) {
6303 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006304 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006305 break;
6306 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006307 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006309 case CFG_USERLIST:
6310 err_code |= cfg_parse_users(file, linenum, args, kwm);
6311 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006312 case CFG_PEERS:
6313 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6314 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006315 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006316 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006317 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006318 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006319
6320 if (err_code & ERR_ABORT)
6321 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006322 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006323 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006324 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006325 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006326 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006327}
6328
Willy Tarreaubb925012009-07-23 13:36:36 +02006329/*
6330 * Returns the error code, 0 if OK, or any combination of :
6331 * - ERR_ABORT: must abort ASAP
6332 * - ERR_FATAL: we can continue parsing but not start the service
6333 * - ERR_WARN: a warning has been emitted
6334 * - ERR_ALERT: an alert has been emitted
6335 * Only the two first ones can stop processing, the two others are just
6336 * indicators.
6337 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006338int check_config_validity()
6339{
6340 int cfgerr = 0;
6341 struct proxy *curproxy = NULL;
6342 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006343 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006344 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006345 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006346 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006347
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006348 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006349 /*
6350 * Now, check for the integrity of all that we have collected.
6351 */
6352
6353 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006354 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355
Willy Tarreau193b8c62012-11-22 00:17:38 +01006356 if (!global.tune.max_http_hdr)
6357 global.tune.max_http_hdr = MAX_HTTP_HDR;
6358
6359 if (!global.tune.cookie_len)
6360 global.tune.cookie_len = CAPTURE_LEN;
6361
6362 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6363
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006364 /* first, we will invert the proxy list order */
6365 curproxy = NULL;
6366 while (proxy) {
6367 struct proxy *next;
6368
6369 next = proxy->next;
6370 proxy->next = curproxy;
6371 curproxy = proxy;
6372 if (!next)
6373 break;
6374 proxy = next;
6375 }
6376
Willy Tarreaubaaee002006-06-26 02:48:02 +02006377 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006378 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006379 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006380 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006381 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006382 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006383 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006384 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006385
Willy Tarreau050536d2012-10-04 08:47:34 +02006386 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006387 /* proxy ID not set, use automatic numbering with first
6388 * spare entry starting with next_pxid.
6389 */
6390 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6391 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6392 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006393 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006394 next_pxid++;
6395
Willy Tarreau55ea7572007-06-17 19:56:27 +02006396
Willy Tarreaubaaee002006-06-26 02:48:02 +02006397 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006398 /* ensure we don't keep listeners uselessly bound */
6399 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006400 curproxy = curproxy->next;
6401 continue;
6402 }
6403
Willy Tarreau16a21472012-11-19 12:39:59 +01006404 /* number of processes this proxy is bound to */
6405 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6406
Willy Tarreauff01a212009-03-15 13:46:16 +01006407 switch (curproxy->mode) {
6408 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006409 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006410 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006411 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6412 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006413 cfgerr++;
6414 }
6415
6416 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006417 Warning("config : servers will be ignored for %s '%s'.\n",
6418 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006419 break;
6420
6421 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006422 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006423 break;
6424
6425 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006426 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006427 break;
6428 }
6429
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006430 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006431 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006432 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006433 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6434 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006435 cfgerr++;
6436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006438 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006439 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6440 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006441 cfgerr++;
6442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006444 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006445 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6446 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006447 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006448 }
6449 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006450 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006451 /* If no LB algo is set in a backend, and we're not in
6452 * transparent mode, dispatch mode nor proxy mode, we
6453 * want to use balance roundrobin by default.
6454 */
6455 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6456 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006457 }
6458 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006459
Willy Tarreau1620ec32011-08-06 17:05:02 +02006460 if (curproxy->options & PR_O_DISPATCH)
6461 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6462 else if (curproxy->options & PR_O_HTTP_PROXY)
6463 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6464 else if (curproxy->options & PR_O_TRANSP)
6465 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006466
Willy Tarreau1620ec32011-08-06 17:05:02 +02006467 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6468 if (curproxy->options & PR_O_DISABLE404) {
6469 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6470 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6471 err_code |= ERR_WARN;
6472 curproxy->options &= ~PR_O_DISABLE404;
6473 }
6474 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6475 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6476 "send-state", proxy_type_str(curproxy), curproxy->id);
6477 err_code |= ERR_WARN;
6478 curproxy->options &= ~PR_O2_CHK_SNDST;
6479 }
Willy Tarreauef781042010-01-27 11:53:01 +01006480 }
6481
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006482 /* if a default backend was specified, let's find it */
6483 if (curproxy->defbe.name) {
6484 struct proxy *target;
6485
Alex Williams96532db2009-11-01 21:27:13 -05006486 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006487 if (!target) {
6488 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6489 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006490 cfgerr++;
6491 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006492 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6493 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006494 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006495 } else {
6496 free(curproxy->defbe.name);
6497 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006498 /* we force the backend to be present on at least all of
6499 * the frontend's processes.
6500 */
6501 target->bind_proc = curproxy->bind_proc ?
6502 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006503
6504 /* Emit a warning if this proxy also has some servers */
6505 if (curproxy->srv) {
6506 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6507 curproxy->id);
6508 err_code |= ERR_WARN;
6509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006510 }
6511 }
6512
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006513 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006514 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6515 /* map jump target for ACT_SETBE in req_rep chain */
6516 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006517 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006518 struct proxy *target;
6519
Willy Tarreaua496b602006-12-17 23:15:24 +01006520 if (exp->action != ACT_SETBE)
6521 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006522
Alex Williams96532db2009-11-01 21:27:13 -05006523 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006524 if (!target) {
6525 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6526 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006527 cfgerr++;
6528 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006529 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6530 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006531 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006532 } else {
6533 free((void *)exp->replace);
6534 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006535 /* we force the backend to be present on at least all of
6536 * the frontend's processes.
6537 */
6538 target->bind_proc = curproxy->bind_proc ?
6539 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006540 }
6541 }
6542 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006543
6544 /* find the target proxy for 'use_backend' rules */
6545 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006546 struct proxy *target;
6547
Alex Williams96532db2009-11-01 21:27:13 -05006548 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006549
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006550 if (!target) {
6551 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6552 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006553 cfgerr++;
6554 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006555 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6556 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006557 cfgerr++;
6558 } else {
6559 free((void *)rule->be.name);
6560 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006561 /* we force the backend to be present on at least all of
6562 * the frontend's processes.
6563 */
6564 target->bind_proc = curproxy->bind_proc ?
6565 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006566 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006567 }
6568
6569 /* find the target proxy for 'use_backend' rules */
6570 list_for_each_entry(srule, &curproxy->server_rules, list) {
6571 struct server *target = findserver(curproxy, srule->srv.name);
6572
6573 if (!target) {
6574 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6575 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6576 cfgerr++;
6577 continue;
6578 }
6579 free((void *)srule->srv.name);
6580 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006581 }
6582
Emeric Brunb982a3d2010-01-04 15:45:53 +01006583 /* find the target table for 'stick' rules */
6584 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6585 struct proxy *target;
6586
Emeric Brun1d33b292010-01-04 15:47:17 +01006587 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6588 if (mrule->flags & STK_IS_STORE)
6589 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6590
Emeric Brunb982a3d2010-01-04 15:45:53 +01006591 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006592 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006593 else
6594 target = curproxy;
6595
6596 if (!target) {
6597 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6598 curproxy->id, mrule->table.name);
6599 cfgerr++;
6600 }
6601 else if (target->table.size == 0) {
6602 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6603 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6604 cfgerr++;
6605 }
Willy Tarreau12785782012-04-27 21:37:17 +02006606 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6607 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006608 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6609 cfgerr++;
6610 }
6611 else {
6612 free((void *)mrule->table.name);
6613 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006614 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006615 }
6616 }
6617
6618 /* find the target table for 'store response' rules */
6619 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6620 struct proxy *target;
6621
Emeric Brun1d33b292010-01-04 15:47:17 +01006622 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6623
Emeric Brunb982a3d2010-01-04 15:45:53 +01006624 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006625 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006626 else
6627 target = curproxy;
6628
6629 if (!target) {
6630 Alert("Proxy '%s': unable to find store table '%s'.\n",
6631 curproxy->id, mrule->table.name);
6632 cfgerr++;
6633 }
6634 else if (target->table.size == 0) {
6635 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6636 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6637 cfgerr++;
6638 }
Willy Tarreau12785782012-04-27 21:37:17 +02006639 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6640 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006641 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6642 cfgerr++;
6643 }
6644 else {
6645 free((void *)mrule->table.name);
6646 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006647 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006648 }
6649 }
6650
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006651 /* find the target table for 'tcp-request' layer 4 rules */
6652 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6653 struct proxy *target;
6654
Willy Tarreaub4c84932013-07-23 19:15:30 +02006655 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006656 continue;
6657
6658 if (trule->act_prm.trk_ctr.table.n)
6659 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6660 else
6661 target = curproxy;
6662
6663 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006664 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6665 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006666 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006667 cfgerr++;
6668 }
6669 else if (target->table.size == 0) {
6670 Alert("Proxy '%s': table '%s' used but not configured.\n",
6671 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6672 cfgerr++;
6673 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006674 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6675 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6676 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006677 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006678 cfgerr++;
6679 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006680 else {
6681 free(trule->act_prm.trk_ctr.table.n);
6682 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006683 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006684 * to pass a list of counters to track and allocate them right here using
6685 * stktable_alloc_data_type().
6686 */
6687 }
6688 }
6689
Willy Tarreaud1f96522010-08-03 19:34:32 +02006690 /* find the target table for 'tcp-request' layer 6 rules */
6691 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6692 struct proxy *target;
6693
Willy Tarreaub4c84932013-07-23 19:15:30 +02006694 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006695 continue;
6696
6697 if (trule->act_prm.trk_ctr.table.n)
6698 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6699 else
6700 target = curproxy;
6701
6702 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006703 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6704 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006705 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006706 cfgerr++;
6707 }
6708 else if (target->table.size == 0) {
6709 Alert("Proxy '%s': table '%s' used but not configured.\n",
6710 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6711 cfgerr++;
6712 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006713 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6714 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6715 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006716 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006717 cfgerr++;
6718 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006719 else {
6720 free(trule->act_prm.trk_ctr.table.n);
6721 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006722 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006723 * to pass a list of counters to track and allocate them right here using
6724 * stktable_alloc_data_type().
6725 */
6726 }
6727 }
6728
Emeric Brun32da3c42010-09-23 18:39:19 +02006729 if (curproxy->table.peers.name) {
6730 struct peers *curpeers = peers;
6731
6732 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6733 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6734 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006735 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006736 break;
6737 }
6738 }
6739
6740 if (!curpeers) {
6741 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6742 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006743 free((void *)curproxy->table.peers.name);
6744 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006745 cfgerr++;
6746 }
6747 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006748 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6749 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006750 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006751 cfgerr++;
6752 }
6753 }
6754
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006755 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006756 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006757 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6758 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6759 "proxy", curproxy->id);
6760 cfgerr++;
6761 goto out_uri_auth_compat;
6762 }
6763
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006764 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006765 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006766 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006767 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006768
Willy Tarreau95fa4692010-02-01 13:05:50 +01006769 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6770 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006771
6772 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006773 uri_auth_compat_req[i++] = "realm";
6774 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6775 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006776
Willy Tarreau95fa4692010-02-01 13:05:50 +01006777 uri_auth_compat_req[i++] = "unless";
6778 uri_auth_compat_req[i++] = "{";
6779 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6780 uri_auth_compat_req[i++] = "}";
6781 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006782
Willy Tarreauff011f22011-01-06 17:51:27 +01006783 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6784 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006785 cfgerr++;
6786 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006787 }
6788
Willy Tarreauff011f22011-01-06 17:51:27 +01006789 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006790
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006791 if (curproxy->uri_auth->auth_realm) {
6792 free(curproxy->uri_auth->auth_realm);
6793 curproxy->uri_auth->auth_realm = NULL;
6794 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006795
6796 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006797 }
6798out_uri_auth_compat:
6799
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006800 /* compile the log format */
6801 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006802 if (curproxy->conf.logformat_string != default_http_log_format &&
6803 curproxy->conf.logformat_string != default_tcp_log_format &&
6804 curproxy->conf.logformat_string != clf_http_log_format)
6805 free(curproxy->conf.logformat_string);
6806 curproxy->conf.logformat_string = NULL;
6807 free(curproxy->conf.lfs_file);
6808 curproxy->conf.lfs_file = NULL;
6809 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006810 }
6811
Willy Tarreau62a61232013-04-12 18:13:46 +02006812 if (curproxy->conf.logformat_string) {
6813 curproxy->conf.args.ctx = ARGC_LOG;
6814 curproxy->conf.args.file = curproxy->conf.lfs_file;
6815 curproxy->conf.args.line = curproxy->conf.lfs_line;
6816 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006817 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006818 curproxy->conf.args.file = NULL;
6819 curproxy->conf.args.line = 0;
6820 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006821
Willy Tarreau62a61232013-04-12 18:13:46 +02006822 if (curproxy->conf.uniqueid_format_string) {
6823 curproxy->conf.args.ctx = ARGC_UIF;
6824 curproxy->conf.args.file = curproxy->conf.uif_file;
6825 curproxy->conf.args.line = curproxy->conf.uif_line;
6826 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006827 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006828 curproxy->conf.args.file = NULL;
6829 curproxy->conf.args.line = 0;
6830 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006831
6832 /* only now we can check if some args remain unresolved */
6833 cfgerr += smp_resolve_args(curproxy);
6834 if (!cfgerr)
6835 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006836
Willy Tarreau2738a142006-07-08 17:28:09 +02006837 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006838 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006839 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006840 (!curproxy->timeout.connect ||
6841 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006842 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006843 " | While not properly invalid, you will certainly encounter various problems\n"
6844 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006845 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006846 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006847 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006848 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006849
Willy Tarreau1fa31262007-12-03 00:36:16 +01006850 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6851 * We must still support older configurations, so let's find out whether those
6852 * parameters have been set or must be copied from contimeouts.
6853 */
6854 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006855 if (!curproxy->timeout.tarpit ||
6856 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006857 /* tarpit timeout not set. We search in the following order:
6858 * default.tarpit, curr.connect, default.connect.
6859 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006860 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006861 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006862 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006863 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006864 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006865 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006866 }
6867 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006868 (!curproxy->timeout.queue ||
6869 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006870 /* queue timeout not set. We search in the following order:
6871 * default.queue, curr.connect, default.connect.
6872 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006873 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006874 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006875 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006876 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006877 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006878 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006879 }
6880 }
6881
Willy Tarreau1620ec32011-08-06 17:05:02 +02006882 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006883 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6884 curproxy->check_req = (char *)malloc(curproxy->check_len);
6885 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006886 }
6887
Willy Tarreau193b8c62012-11-22 00:17:38 +01006888 /* ensure that cookie capture length is not too large */
6889 if (curproxy->capture_len >= global.tune.cookie_len) {
6890 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6891 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6892 err_code |= ERR_WARN;
6893 curproxy->capture_len = global.tune.cookie_len - 1;
6894 }
6895
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006896 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006897 if (curproxy->nb_req_cap) {
6898 if (curproxy->mode == PR_MODE_HTTP) {
6899 curproxy->req_cap_pool = create_pool("ptrcap",
6900 curproxy->nb_req_cap * sizeof(char *),
6901 MEM_F_SHARED);
6902 } else {
6903 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6904 proxy_type_str(curproxy), curproxy->id);
6905 err_code |= ERR_WARN;
6906 curproxy->to_log &= ~LW_REQHDR;
6907 curproxy->nb_req_cap = 0;
6908 }
6909 }
6910
6911 if (curproxy->nb_rsp_cap) {
6912 if (curproxy->mode == PR_MODE_HTTP) {
6913 curproxy->rsp_cap_pool = create_pool("ptrcap",
6914 curproxy->nb_rsp_cap * sizeof(char *),
6915 MEM_F_SHARED);
6916 } else {
6917 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6918 proxy_type_str(curproxy), curproxy->id);
6919 err_code |= ERR_WARN;
6920 curproxy->to_log &= ~LW_REQHDR;
6921 curproxy->nb_rsp_cap = 0;
6922 }
6923 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006924
Willy Tarreaubaaee002006-06-26 02:48:02 +02006925 /* first, we will invert the servers list order */
6926 newsrv = NULL;
6927 while (curproxy->srv) {
6928 struct server *next;
6929
6930 next = curproxy->srv->next;
6931 curproxy->srv->next = newsrv;
6932 newsrv = curproxy->srv;
6933 if (!next)
6934 break;
6935 curproxy->srv = next;
6936 }
6937
Willy Tarreaudd701652010-05-25 23:03:02 +02006938 /* assign automatic UIDs to servers which don't have one yet */
6939 next_id = 1;
6940 newsrv = curproxy->srv;
6941 while (newsrv != NULL) {
6942 if (!newsrv->puid) {
6943 /* server ID not set, use automatic numbering with first
6944 * spare entry starting with next_svid.
6945 */
6946 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6947 newsrv->conf.id.key = newsrv->puid = next_id;
6948 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6949 }
6950 next_id++;
6951 newsrv = newsrv->next;
6952 }
6953
Willy Tarreau20697042007-11-15 23:26:18 +01006954 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006955 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006956
Willy Tarreau62c3be22012-01-20 13:12:32 +01006957 /*
6958 * If this server supports a maxconn parameter, it needs a dedicated
6959 * tasks to fill the emptied slots when a connection leaves.
6960 * Also, resolve deferred tracking dependency if needed.
6961 */
6962 newsrv = curproxy->srv;
6963 while (newsrv != NULL) {
6964 if (newsrv->minconn > newsrv->maxconn) {
6965 /* Only 'minconn' was specified, or it was higher than or equal
6966 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6967 * this will avoid further useless expensive computations.
6968 */
6969 newsrv->maxconn = newsrv->minconn;
6970 } else if (newsrv->maxconn && !newsrv->minconn) {
6971 /* minconn was not specified, so we set it to maxconn */
6972 newsrv->minconn = newsrv->maxconn;
6973 }
6974
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006975#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006976 if (newsrv->use_ssl || newsrv->check.use_ssl)
6977 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006978#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006979
Willy Tarreau2f075e92013-12-03 11:11:34 +01006980 /* set the check type on the server */
6981 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6982
Willy Tarreau62c3be22012-01-20 13:12:32 +01006983 if (newsrv->trackit) {
6984 struct proxy *px;
6985 struct server *srv;
6986 char *pname, *sname;
6987
6988 pname = newsrv->trackit;
6989 sname = strrchr(pname, '/');
6990
6991 if (sname)
6992 *sname++ = '\0';
6993 else {
6994 sname = pname;
6995 pname = NULL;
6996 }
6997
6998 if (pname) {
6999 px = findproxy(pname, PR_CAP_BE);
7000 if (!px) {
7001 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7002 proxy_type_str(curproxy), curproxy->id,
7003 newsrv->id, pname);
7004 cfgerr++;
7005 goto next_srv;
7006 }
7007 } else
7008 px = curproxy;
7009
7010 srv = findserver(px, sname);
7011 if (!srv) {
7012 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7013 proxy_type_str(curproxy), curproxy->id,
7014 newsrv->id, sname);
7015 cfgerr++;
7016 goto next_srv;
7017 }
7018
7019 if (!(srv->state & SRV_CHECKED)) {
7020 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7021 "tracking as it does not have checks enabled.\n",
7022 proxy_type_str(curproxy), curproxy->id,
7023 newsrv->id, px->id, srv->id);
7024 cfgerr++;
7025 goto next_srv;
7026 }
7027
7028 if (curproxy != px &&
7029 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7030 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7031 "tracking: disable-on-404 option inconsistency.\n",
7032 proxy_type_str(curproxy), curproxy->id,
7033 newsrv->id, px->id, srv->id);
7034 cfgerr++;
7035 goto next_srv;
7036 }
7037
7038 /* if the other server is forced disabled, we have to do the same here */
7039 if (srv->state & SRV_MAINTAIN) {
7040 newsrv->state |= SRV_MAINTAIN;
7041 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007042 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007043 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007044 }
7045
7046 newsrv->track = srv;
7047 newsrv->tracknext = srv->tracknext;
7048 srv->tracknext = newsrv;
7049
7050 free(newsrv->trackit);
7051 newsrv->trackit = NULL;
7052 }
7053 next_srv:
7054 newsrv = newsrv->next;
7055 }
7056
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007057 /* We have to initialize the server lookup mechanism depending
7058 * on what LB algorithm was choosen.
7059 */
7060
7061 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7062 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7063 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007064 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7065 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7066 init_server_map(curproxy);
7067 } else {
7068 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7069 fwrr_init_server_groups(curproxy);
7070 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007071 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007072
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007073 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007074 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7075 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7076 fwlc_init_server_tree(curproxy);
7077 } else {
7078 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7079 fas_init_server_tree(curproxy);
7080 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007081 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007082
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007083 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007084 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7085 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7086 chash_init_server_tree(curproxy);
7087 } else {
7088 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7089 init_server_map(curproxy);
7090 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007091 break;
7092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093
7094 if (curproxy->options & PR_O_LOGASAP)
7095 curproxy->to_log &= ~LW_BYTES;
7096
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007097 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007098 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007099 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7100 proxy_type_str(curproxy), curproxy->id);
7101 err_code |= ERR_WARN;
7102 }
7103
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007104 if (curproxy->mode != PR_MODE_HTTP) {
7105 int optnum;
7106
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007107 if (curproxy->uri_auth) {
7108 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7109 proxy_type_str(curproxy), curproxy->id);
7110 err_code |= ERR_WARN;
7111 curproxy->uri_auth = NULL;
7112 }
7113
Willy Tarreau87cf5142011-08-19 22:57:24 +02007114 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007115 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7116 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7117 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007118 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007119 }
7120
7121 if (curproxy->options & PR_O_ORGTO) {
7122 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7123 "originalto", proxy_type_str(curproxy), curproxy->id);
7124 err_code |= ERR_WARN;
7125 curproxy->options &= ~PR_O_ORGTO;
7126 }
7127
7128 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7129 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7130 (curproxy->cap & cfg_opts[optnum].cap) &&
7131 (curproxy->options & cfg_opts[optnum].val)) {
7132 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7133 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7134 err_code |= ERR_WARN;
7135 curproxy->options &= ~cfg_opts[optnum].val;
7136 }
7137 }
7138
7139 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7140 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7141 (curproxy->cap & cfg_opts2[optnum].cap) &&
7142 (curproxy->options2 & cfg_opts2[optnum].val)) {
7143 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7144 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7145 err_code |= ERR_WARN;
7146 curproxy->options2 &= ~cfg_opts2[optnum].val;
7147 }
7148 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007149
Pieter Baauwd551fb52013-05-08 22:49:23 +02007150#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007151 if (curproxy->conn_src.bind_hdr_occ) {
7152 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007153 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007154 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007155 err_code |= ERR_WARN;
7156 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007157#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007158 }
7159
Willy Tarreaubaaee002006-06-26 02:48:02 +02007160 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007161 * ensure that we're not cross-dressing a TCP server into HTTP.
7162 */
7163 newsrv = curproxy->srv;
7164 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007165 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007166 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7167 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007168 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007169 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007170
Willy Tarreau0cec3312011-10-31 13:49:26 +01007171 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7172 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7173 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7174 err_code |= ERR_WARN;
7175 }
7176
Willy Tarreau82ffa392013-08-13 17:19:08 +02007177 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7178 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7179 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7180 err_code |= ERR_WARN;
7181 }
7182
Pieter Baauwd551fb52013-05-08 22:49:23 +02007183#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007184 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7185 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007186 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 +01007187 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007188 err_code |= ERR_WARN;
7189 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007190#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007191 newsrv = newsrv->next;
7192 }
7193
Willy Tarreauc1a21672009-08-16 22:37:44 +02007194 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007195 if (!curproxy->accept)
7196 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007197
Willy Tarreauc1a21672009-08-16 22:37:44 +02007198 if (curproxy->tcp_req.inspect_delay ||
7199 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007200 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007201
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007202 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007203 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007204 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007205 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007206
7207 /* both TCP and HTTP must check switching rules */
7208 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7209 }
7210
7211 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007212 if (curproxy->tcp_req.inspect_delay ||
7213 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7214 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7215
Emeric Brun97679e72010-09-23 17:56:44 +02007216 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7217 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7218
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007219 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007220 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007221 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007222 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007223
7224 /* If the backend does requires RDP cookie persistence, we have to
7225 * enable the corresponding analyser.
7226 */
7227 if (curproxy->options2 & PR_O2_RDPC_PRST)
7228 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7229 }
7230
Emeric Brunc52962f2012-11-15 18:28:02 +01007231#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007232 /* Configure SSL for each bind line.
7233 * Note: if configuration fails at some point, the ->ctx member
7234 * remains NULL so that listeners can later detach.
7235 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007236 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007237 if (!bind_conf->is_ssl) {
7238 if (bind_conf->default_ctx) {
7239 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7240 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7241 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007242 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007243 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007244 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007245 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007246 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007247 cfgerr++;
7248 continue;
7249 }
7250
Emeric Brun4b3091e2012-09-24 15:48:52 +02007251 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007252 Alert("Unable to allocate SSL session cache.\n");
7253 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007254 continue;
7255 }
7256
Emeric Brunfc0421f2012-09-07 17:30:07 +02007257 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007258 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007259 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007260#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007261
Willy Tarreaue6b98942007-10-29 01:09:36 +01007262 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007263 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007264 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007265 if (!listener->luid) {
7266 /* listener ID not set, use automatic numbering with first
7267 * spare entry starting with next_luid.
7268 */
7269 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7270 listener->conf.id.key = listener->luid = next_id;
7271 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007272 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007273 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007274
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007275 /* enable separate counters */
7276 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7277 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007278 if (!listener->name)
7279 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007280 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007281
Willy Tarreaue6b98942007-10-29 01:09:36 +01007282 if (curproxy->options & PR_O_TCP_NOLING)
7283 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007284 if (!listener->maxconn)
7285 listener->maxconn = curproxy->maxconn;
7286 if (!listener->backlog)
7287 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007288 if (!listener->maxaccept)
7289 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7290
7291 /* we want to have an optimal behaviour on single process mode to
7292 * maximize the work at once, but in multi-process we want to keep
7293 * some fairness between processes, so we target half of the max
7294 * number of events to be balanced over all the processes the proxy
7295 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7296 * used to disable the limit.
7297 */
7298 if (listener->maxaccept > 0) {
7299 if (nbproc > 1)
7300 listener->maxaccept = (listener->maxaccept + 1) / 2;
7301 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7302 }
7303
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007304 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007305 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007306 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007307 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007308
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007309 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7310 listener->options |= LI_O_TCP_RULES;
7311
Willy Tarreaude3041d2010-05-31 10:56:17 +02007312 if (curproxy->mon_mask.s_addr)
7313 listener->options |= LI_O_CHK_MONNET;
7314
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007315 /* smart accept mode is automatic in HTTP mode */
7316 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007317 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007318 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7319 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007320 }
7321
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007322 /* Release unused SSL configs */
7323 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7324 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007325 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007326#ifdef USE_OPENSSL
7327 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007328 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007329 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007330 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007331 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007332#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007333 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007334
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007335 /* Check multi-process mode compatibility for the current proxy */
7336 if (global.nbproc > 1) {
7337 int nbproc = 0;
7338 if (curproxy->bind_proc) {
7339 int proc;
7340 for (proc = 0; proc < global.nbproc; proc++) {
7341 if (curproxy->bind_proc & (1 << proc)) {
7342 nbproc++;
7343 }
7344 }
7345 } else {
7346 nbproc = global.nbproc;
7347 }
7348 if (curproxy->table.peers.name) {
7349 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7350 curproxy->id);
7351 cfgerr++;
7352 }
7353 if (nbproc > 1) {
7354 if (curproxy->uri_auth) {
7355 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7356 curproxy->id);
7357 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7358 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7359 curproxy->id);
7360 }
7361 }
7362 if (curproxy->appsession_name) {
7363 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7364 curproxy->id);
7365 }
7366 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7367 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7368 curproxy->id);
7369 }
7370 }
7371 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007372
7373 /* create the task associated with the proxy */
7374 curproxy->task = task_new();
7375 if (curproxy->task) {
7376 curproxy->task->context = curproxy;
7377 curproxy->task->process = manage_proxy;
7378 /* no need to queue, it will be done automatically if some
7379 * listener gets limited.
7380 */
7381 curproxy->task->expire = TICK_ETERNITY;
7382 } else {
7383 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7384 curproxy->id);
7385 cfgerr++;
7386 }
7387
Willy Tarreaubaaee002006-06-26 02:48:02 +02007388 curproxy = curproxy->next;
7389 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007390
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007391 /* Check multi-process mode compatibility */
7392 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007393 if (global.stats_fe && !global.stats_fe->bind_proc) {
7394 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 +01007395 }
7396 }
7397
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007398 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7399 struct auth_users *curuser;
7400 int g;
7401
7402 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7403 unsigned int group_mask = 0;
7404 char *group = NULL;
7405
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007406 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007407 continue;
7408
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007409 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007410
7411 for (g = 0; g < curuserlist->grpcnt; g++)
7412 if (!strcmp(curuserlist->groups[g], group))
7413 break;
7414
7415 if (g == curuserlist->grpcnt) {
7416 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7417 curuserlist->name, group, curuser->user);
7418 err_code |= ERR_ALERT | ERR_FATAL;
7419 goto out;
7420 }
7421
7422 group_mask |= (1 << g);
7423 }
7424
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007425 free(curuser->u.groups);
7426 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007427 }
7428
7429 for (g = 0; g < curuserlist->grpcnt; g++) {
7430 char *user = NULL;
7431
7432 if (!curuserlist->groupusers[g])
7433 continue;
7434
7435 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7436 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7437 if (!strcmp(curuser->user, user))
7438 break;
7439
7440 if (!curuser) {
7441 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7442 curuserlist->name, user, curuserlist->groups[g]);
7443 err_code |= ERR_ALERT | ERR_FATAL;
7444 goto out;
7445 }
7446
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007447 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007448 }
7449
7450 free(curuserlist->groupusers[g]);
7451 }
7452
7453 free(curuserlist->groupusers);
7454
7455#ifdef DEBUG_AUTH
7456 for (g = 0; g < curuserlist->grpcnt; g++) {
7457 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7458
7459 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007460 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007461 fprintf(stderr, " %s", curuser->user);
7462 }
7463
7464 fprintf(stderr, "\n");
7465 }
7466#endif
7467
Willy Tarreaufbb78422011-06-05 15:38:35 +02007468 }
7469
7470 /* automatically compute fullconn if not set. We must not do it in the
7471 * loop above because cross-references are not yet fully resolved.
7472 */
7473 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7474 /* If <fullconn> is not set, let's set it to 10% of the sum of
7475 * the possible incoming frontend's maxconns.
7476 */
7477 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7478 struct proxy *fe;
7479 int total = 0;
7480
7481 /* sum up the number of maxconns of frontends which
7482 * reference this backend at least once or which are
7483 * the same one ('listen').
7484 */
7485 for (fe = proxy; fe; fe = fe->next) {
7486 struct switching_rule *rule;
7487 struct hdr_exp *exp;
7488 int found = 0;
7489
7490 if (!(fe->cap & PR_CAP_FE))
7491 continue;
7492
7493 if (fe == curproxy) /* we're on a "listen" instance */
7494 found = 1;
7495
7496 if (fe->defbe.be == curproxy) /* "default_backend" */
7497 found = 1;
7498
7499 /* check if a "use_backend" rule matches */
7500 if (!found) {
7501 list_for_each_entry(rule, &fe->switching_rules, list) {
7502 if (rule->be.backend == curproxy) {
7503 found = 1;
7504 break;
7505 }
7506 }
7507 }
7508
7509 /* check if a "reqsetbe" rule matches */
7510 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7511 if (exp->action == ACT_SETBE &&
7512 (struct proxy *)exp->replace == curproxy) {
7513 found = 1;
7514 break;
7515 }
7516 }
7517
7518 /* now we've checked all possible ways to reference a backend
7519 * from a frontend.
7520 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007521 if (!found)
7522 continue;
7523 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007524 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007525 /* we have the sum of the maxconns in <total>. We only
7526 * keep 10% of that sum to set the default fullconn, with
7527 * a hard minimum of 1 (to avoid a divide by zero).
7528 */
7529 curproxy->fullconn = (total + 9) / 10;
7530 if (!curproxy->fullconn)
7531 curproxy->fullconn = 1;
7532 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007533 }
7534
Willy Tarreau056f5682010-06-06 15:51:11 +02007535 /* initialize stick-tables on backend capable proxies. This must not
7536 * be done earlier because the data size may be discovered while parsing
7537 * other proxies.
7538 */
Godbach9703e662013-12-11 21:11:41 +08007539 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7540 if (!stktable_init(&curproxy->table)) {
7541 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7542 cfgerr++;
7543 }
7544 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007545
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007546 /*
7547 * Recount currently required checks.
7548 */
7549
7550 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7551 int optnum;
7552
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007553 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7554 if (curproxy->options & cfg_opts[optnum].val)
7555 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007556
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007557 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7558 if (curproxy->options2 & cfg_opts2[optnum].val)
7559 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007560 }
7561
Willy Tarreau122541c2011-09-07 21:24:49 +02007562 if (peers) {
7563 struct peers *curpeers = peers, **last;
7564 struct peer *p, *pb;
7565
7566 /* Remove all peers sections which don't have a valid listener.
7567 * This can happen when a peers section is never referenced and
7568 * does not contain a local peer.
7569 */
7570 last = &peers;
7571 while (*last) {
7572 curpeers = *last;
7573 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007574 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007575 last = &curpeers->next;
7576 continue;
7577 }
7578
7579 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7580 curpeers->id, localpeer);
7581
7582 p = curpeers->remote;
7583 while (p) {
7584 pb = p->next;
7585 free(p->id);
7586 free(p);
7587 p = pb;
7588 }
7589
7590 /* Destroy and unlink this curpeers section.
7591 * Note: curpeers is backed up into *last.
7592 */
7593 free(curpeers->id);
7594 curpeers = curpeers->next;
7595 free(*last);
7596 *last = curpeers;
7597 }
7598 }
7599
Willy Tarreau34eb6712011-10-24 18:15:04 +02007600 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007601 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007602 MEM_F_SHARED);
7603
Willy Tarreaubb925012009-07-23 13:36:36 +02007604 if (cfgerr > 0)
7605 err_code |= ERR_ALERT | ERR_FATAL;
7606 out:
7607 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007608}
7609
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007610/*
7611 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7612 * parsing sessions.
7613 */
7614void cfg_register_keywords(struct cfg_kw_list *kwl)
7615{
7616 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7617}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007618
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007619/*
7620 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7621 */
7622void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7623{
7624 LIST_DEL(&kwl->list);
7625 LIST_INIT(&kwl->list);
7626}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007627
7628/*
7629 * Local variables:
7630 * c-indent-level: 8
7631 * c-basic-offset: 8
7632 * End:
7633 */