blob: b3435ef6fb5f63053366d0137d283650616e47d2 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100209 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100210 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
212 str = next;
213 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100214 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 *next++ = 0;
216 }
217
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100218 ss2 = str2sa_range(str, &port, &end, err,
219 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
220 if (!ss2)
221 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100223 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100224 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100229 if (!port || !end) {
230 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
231 goto fail;
232 }
233
Emeric Bruned760922010-10-22 17:59:25 +0200234 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200235 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200236 goto fail;
237 }
238
239 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200240 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 else if (ss2->ss_family == AF_UNSPEC) {
245 socklen_t addr_len;
246
247 /* We want to attach to an already bound fd whose number
248 * is in the addr part of ss2 when cast to sockaddr_in.
249 * Note that by definition there is a single listener.
250 * We still have to determine the address family to
251 * register the correct protocol.
252 */
253 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
254 addr_len = sizeof(*ss2);
255 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
256 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
257 goto fail;
258 }
259
260 port = end = get_host_port(ss2);
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100263 /* OK the address looks correct */
264 ss = *ss2;
265
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100268 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200269 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
270 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
271 l->frontend = curproxy;
272 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273
Willy Tarreau40aa0702013-03-10 23:51:38 +0100274 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200276 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100277 l->state = LI_INIT;
278
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100279 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100281 tcpv4_add_listener(l);
282 }
Emeric Bruned760922010-10-22 17:59:25 +0200283 else if (ss.ss_family == AF_INET6) {
284 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
285 tcpv6_add_listener(l);
286 }
287 else {
Emeric Bruned760922010-10-22 17:59:25 +0200288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100417/* Report it if a request ACL condition uses some keywords that are incompatible
418 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
419 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
420 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100421 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100422static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200425 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100428 return 0;
429
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100430 acl = acl_cond_conflicts(cond, where);
431 if (acl) {
432 if (acl->name && *acl->name)
433 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
434 file, line, acl->name, sample_ckp_names(where));
435 else
436 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200437 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100438 return ERR_WARN;
439 }
440 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100441 return 0;
442
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 if (acl->name && *acl->name)
444 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446 else
447 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200448 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100449 return ERR_WARN;
450}
451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200471 else if (!strcmp(args[0], "ca-base")) {
472#ifdef USE_OPENSSL
473 if (global.ca_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.ca_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
490 else if (!strcmp(args[0], "crt-base")) {
491#ifdef USE_OPENSSL
492 if (global.crt_base != NULL) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.crt_base = strdup(args[1]);
503#else
504 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507#endif
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "daemon")) {
510 global.mode |= MODE_DAEMON;
511 }
512 else if (!strcmp(args[0], "debug")) {
513 global.mode |= MODE_DEBUG;
514 }
515 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200518 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100524 else if (!strcmp(args[0], "nosplice")) {
525 global.tune.options &= ~GTUNE_USE_SPLICE;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "quiet")) {
528 global.mode |= MODE_QUIET;
529 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200530 else if (!strcmp(args[0], "tune.maxpollevents")) {
531 if (global.tune.maxpollevents != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200540 }
541 global.tune.maxpollevents = atol(args[1]);
542 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100543 else if (!strcmp(args[0], "tune.maxaccept")) {
544 if (global.tune.maxaccept != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100553 }
554 global.tune.maxaccept = atol(args[1]);
555 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200556 else if (!strcmp(args[0], "tune.chksize")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.chksize = atol(args[1]);
563 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200564#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100565 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.sslcachesize = atol(args[1]);
572 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100573 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
574 unsigned int ssllifetime;
575 const char *res;
576
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582
583 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
584 if (res) {
585 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
586 file, linenum, *res, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590
591 global.tune.ssllifetime = ssllifetime;
592 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100593 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.ssl_max_record = atol(args[1]);
600 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200602 else if (!strcmp(args[0], "tune.bufsize")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.bufsize = atol(args[1]);
609 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
610 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100611 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200612 }
613 else if (!strcmp(args[0], "tune.maxrewrite")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.maxrewrite = atol(args[1]);
620 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
621 global.tune.maxrewrite = global.tune.bufsize / 2;
622 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100623 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
624 if (global.tune.client_rcvbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_rcvbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
637 if (global.tune.server_rcvbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_rcvbuf = atol(args[1]);
648 }
649 else if (!strcmp(args[0], "tune.sndbuf.client")) {
650 if (global.tune.client_sndbuf != 0) {
651 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT;
653 goto out;
654 }
655 if (*(args[1]) == 0) {
656 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT | ERR_FATAL;
658 goto out;
659 }
660 global.tune.client_sndbuf = atol(args[1]);
661 }
662 else if (!strcmp(args[0], "tune.sndbuf.server")) {
663 if (global.tune.server_sndbuf != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT;
666 goto out;
667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673 global.tune.server_sndbuf = atol(args[1]);
674 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200675 else if (!strcmp(args[0], "tune.pipesize")) {
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.tune.pipesize = atol(args[1]);
682 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100683 else if (!strcmp(args[0], "tune.http.cookielen")) {
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689 global.tune.cookie_len = atol(args[1]) + 1;
690 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200691 else if (!strcmp(args[0], "tune.http.maxhdr")) {
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 global.tune.max_http_hdr = atol(args[1]);
698 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100699 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
700#ifdef USE_ZLIB
701 if (*args[1]) {
702 global.tune.zlibmemlevel = atoi(args[1]);
703 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
704 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
705 file, linenum, args[0]);
706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
708 }
709 } else {
710 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715#else
716 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719#endif
720 }
721 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
722#ifdef USE_ZLIB
723 if (*args[1]) {
724 global.tune.zlibwindowsize = atoi(args[1]);
725 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
726 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
727 file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 } else {
732 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
733 file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737#else
738 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741#endif
742 }
William Lallemandf3747832012-11-09 12:33:10 +0100743 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
744 if (*args[1]) {
745 global.tune.comp_maxlevel = atoi(args[1]);
746 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
747 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
748 file, linenum, args[0]);
749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
751 }
752 } else {
753 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
754 file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 else if (!strcmp(args[0], "uid")) {
760 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200761 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200762 err_code |= ERR_ALERT;
763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770 global.uid = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "gid")) {
773 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200774 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT;
776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
783 global.gid = atol(args[1]);
784 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 /* user/group name handling */
786 else if (!strcmp(args[0], "user")) {
787 struct passwd *ha_user;
788 if (global.uid != 0) {
789 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200792 }
793 errno = 0;
794 ha_user = getpwnam(args[1]);
795 if (ha_user != NULL) {
796 global.uid = (int)ha_user->pw_uid;
797 }
798 else {
799 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200801 }
802 }
803 else if (!strcmp(args[0], "group")) {
804 struct group *ha_group;
805 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200806 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT;
808 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200809 }
810 errno = 0;
811 ha_group = getgrnam(args[1]);
812 if (ha_group != NULL) {
813 global.gid = (int)ha_group->gr_gid;
814 }
815 else {
816 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200818 }
819 }
820 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 global.nbproc = atol(args[1]);
828 }
829 else if (!strcmp(args[0], "maxconn")) {
830 if (global.maxconn != 0) {
831 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT;
833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840 global.maxconn = atol(args[1]);
841#ifdef SYSTEM_MAXCONN
842 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
843 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
844 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847#endif /* SYSTEM_MAXCONN */
848 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200849 else if (!strcmp(args[0], "maxsslconn")) {
850#ifdef USE_OPENSSL
851 if (*(args[1]) == 0) {
852 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
853 err_code |= ERR_ALERT | ERR_FATAL;
854 goto out;
855 }
856 global.maxsslconn = atol(args[1]);
857#else
Emeric Brun0914df82012-10-02 18:45:42 +0200858 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200861#endif
862 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200863 else if (!strcmp(args[0], "maxconnrate")) {
864 if (global.cps_lim != 0) {
865 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT;
867 goto out;
868 }
869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.cps_lim = atol(args[1]);
875 }
William Lallemandd85f9172012-11-09 17:05:39 +0100876 else if (!strcmp(args[0], "maxcomprate")) {
877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 global.comp_rate_lim = atoi(args[1]) * 1024;
883 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100884 else if (!strcmp(args[0], "maxpipes")) {
885 if (global.maxpipes != 0) {
886 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_ALERT;
888 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100889 }
890 if (*(args[1]) == 0) {
891 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100894 }
895 global.maxpipes = atol(args[1]);
896 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 else if (!strcmp(args[0], "maxzlibmem")) {
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
William Lallemande3a7d992012-11-20 11:25:20 +0100903 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100904 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100905 else if (!strcmp(args[0], "maxcompcpuusage")) {
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100912 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100913 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917}
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 else if (!strcmp(args[0], "ulimit-n")) {
920 if (global.rlimit_nofile != 0) {
921 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
925 if (*(args[1]) == 0) {
926 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930 global.rlimit_nofile = atol(args[1]);
931 }
932 else if (!strcmp(args[0], "chroot")) {
933 if (global.chroot != NULL) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 global.chroot = strdup(args[1]);
944 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200945 else if (!strcmp(args[0], "description")) {
946 int i, len=0;
947 char *d;
948
949 if (!*args[1]) {
950 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
951 file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 for(i=1; *args[i]; i++)
957 len += strlen(args[i])+1;
958
959 if (global.desc)
960 free(global.desc);
961
962 global.desc = d = (char *)calloc(1, len);
963
964 d += sprintf(d, "%s", args[1]);
965 for(i=2; *args[i]; i++)
966 d += sprintf(d, " %s", args[i]);
967 }
968 else if (!strcmp(args[0], "node")) {
969 int i;
970 char c;
971
972 for (i=0; args[1][i]; i++) {
973 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100974 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
975 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200976 break;
977 }
978
979 if (!i || args[1][i]) {
980 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
981 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
982 file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
986
987 if (global.node)
988 free(global.node);
989
990 global.node = strdup(args[1]);
991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "pidfile")) {
993 if (global.pidfile != NULL) {
994 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 }
1003 global.pidfile = strdup(args[1]);
1004 }
Emeric Bruned760922010-10-22 17:59:25 +02001005 else if (!strcmp(args[0], "unix-bind")) {
1006 int cur_arg = 1;
1007 while (*(args[cur_arg])) {
1008 if (!strcmp(args[cur_arg], "prefix")) {
1009 if (global.unix_bind.prefix != NULL) {
1010 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT;
1012 cur_arg += 2;
1013 continue;
1014 }
1015
1016 if (*(args[cur_arg+1]) == 0) {
1017 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020 }
1021 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "mode")) {
1027
1028 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "uid")) {
1034
1035 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "gid")) {
1041
1042 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1043 cur_arg += 2;
1044 continue;
1045 }
1046
1047 if (!strcmp(args[cur_arg], "user")) {
1048 struct passwd *user;
1049
1050 user = getpwnam(args[cur_arg + 1]);
1051 if (!user) {
1052 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1053 file, linenum, args[0], args[cur_arg + 1 ]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057
1058 global.unix_bind.ux.uid = user->pw_uid;
1059 cur_arg += 2;
1060 continue;
1061 }
1062
1063 if (!strcmp(args[cur_arg], "group")) {
1064 struct group *group;
1065
1066 group = getgrnam(args[cur_arg + 1]);
1067 if (!group) {
1068 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1069 file, linenum, args[0], args[cur_arg + 1 ]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073
1074 global.unix_bind.ux.gid = group->gr_gid;
1075 cur_arg += 2;
1076 continue;
1077 }
1078
Willy Tarreaub48f9582011-09-05 01:17:06 +02001079 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001080 file, linenum, args[0]);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084 }
William Lallemand0f99e342011-10-12 17:50:54 +02001085 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1086 /* delete previous herited or defined syslog servers */
1087 struct logsrv *back;
1088 struct logsrv *tmp;
1089
1090 if (*(args[1]) != 0) {
1091 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095
1096 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1097 LIST_DEL(&tmp->list);
1098 free(tmp);
1099 }
1100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001102 struct sockaddr_storage *sk;
1103 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001104 struct logsrv *logsrv;
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 if (*(args[1]) == 0 || *(args[2]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
William Lallemand0f99e342011-10-12 17:50:54 +02001111
1112 logsrv = calloc(1, sizeof(struct logsrv));
1113
1114 logsrv->facility = get_log_facility(args[2]);
1115 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120
William Lallemand0f99e342011-10-12 17:50:54 +02001121 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001123 logsrv->level = get_log_level(args[3]);
1124 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001127 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 }
1130
William Lallemand0f99e342011-10-12 17:50:54 +02001131 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001132 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001133 logsrv->minlvl = get_log_level(args[4]);
1134 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001135 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001137 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001138 }
1139 }
1140
Willy Tarreau902636f2013-03-10 19:44:48 +01001141 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001142 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001143 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001144 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001145 free(logsrv);
1146 goto out;
1147 }
1148 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001149
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001150 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001151 if (port1 != port2) {
1152 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1153 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001154 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001155 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001156 goto out;
1157 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001158
William Lallemand0f99e342011-10-12 17:50:54 +02001159 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001160 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001161 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163
William Lallemand0f99e342011-10-12 17:50:54 +02001164 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001165 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001166 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1167 char *name;
1168 int len;
1169
1170 if (global.log_send_hostname != NULL) {
1171 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT;
1173 goto out;
1174 }
1175
1176 if (*(args[1]))
1177 name = args[1];
1178 else
1179 name = hostname;
1180
1181 len = strlen(name);
1182
1183 /* We'll add a space after the name to respect the log format */
1184 free(global.log_send_hostname);
1185 global.log_send_hostname = malloc(len + 2);
1186 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1187 }
Kevinm48936af2010-12-22 16:08:21 +00001188 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
1193 }
1194 free(global.log_tag);
1195 global.log_tag = strdup(args[1]);
1196 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001197 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1198 if (global.spread_checks != 0) {
1199 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001207 }
1208 global.spread_checks = atol(args[1]);
1209 if (global.spread_checks < 0 || global.spread_checks > 50) {
1210 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001211 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001214 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1215#ifdef USE_CPU_AFFINITY
1216 int cur_arg, i;
1217 unsigned int proc = 0;
1218 unsigned long cpus = 0;
1219
1220 if (strcmp(args[1], "all") == 0)
1221 proc = 0xFFFFFFFF;
1222 else if (strcmp(args[1], "odd") == 0)
1223 proc = 0x55555555;
1224 else if (strcmp(args[1], "even") == 0)
1225 proc = 0xAAAAAAAA;
1226 else {
1227 proc = atoi(args[1]);
1228 if (proc >= 1 && proc <= 32)
1229 proc = 1 << (proc - 1);
1230 }
1231
1232 if (!proc || !*args[2]) {
1233 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1234 file, linenum, args[0]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 cur_arg = 2;
1240 while (*args[cur_arg]) {
1241 unsigned int low, high;
1242
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001243 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001244 char *dash = strchr(args[cur_arg], '-');
1245
1246 low = high = str2uic(args[cur_arg]);
1247 if (dash)
1248 high = str2uic(dash + 1);
1249
1250 if (high < low) {
1251 unsigned int swap = low;
1252 low = high;
1253 high = swap;
1254 }
1255
1256 if (low < 0 || high >= sizeof(long) * 8) {
1257 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1258 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 while (low <= high)
1264 cpus |= 1UL << low++;
1265 }
1266 else {
1267 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1268 file, linenum, args[0], args[cur_arg]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 cur_arg++;
1273 }
1274 for (i = 0; i < 32; i++)
1275 if (proc & (1 << i))
1276 global.cpu_map[i] = cpus;
1277#else
1278 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281#endif
1282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001284 struct cfg_kw_list *kwl;
1285 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001286 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001287
1288 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1289 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1290 if (kwl->kw[index].section != CFG_GLOBAL)
1291 continue;
1292 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001293 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001294 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001295 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001297 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001298 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001299 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_WARN;
1301 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001302 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001304 }
1305 }
1306 }
1307
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001311
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001313 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315}
1316
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001317void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001319 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 defproxy.mode = PR_MODE_TCP;
1321 defproxy.state = PR_STNEW;
1322 defproxy.maxconn = cfg_maxpconn;
1323 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001324
1325 defproxy.defsrv.inter = DEF_CHKINTR;
1326 defproxy.defsrv.fastinter = 0;
1327 defproxy.defsrv.downinter = 0;
1328 defproxy.defsrv.rise = DEF_RISETIME;
1329 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001330 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001331 defproxy.defsrv.maxqueue = 0;
1332 defproxy.defsrv.minconn = 0;
1333 defproxy.defsrv.maxconn = 0;
1334 defproxy.defsrv.slowstart = 0;
1335 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1336 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1337 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338}
1339
Willy Tarreauade5ec42010-01-28 19:33:49 +01001340
1341static int create_cond_regex_rule(const char *file, int line,
1342 struct proxy *px, int dir, int action, int flags,
1343 const char *cmd, const char *reg, const char *repl,
1344 const char **cond_start)
1345{
1346 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001347 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001348 const char *err;
1349 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001350 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001351
1352 if (px == &defproxy) {
1353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto err;
1356 }
1357
1358 if (*reg == 0) {
1359 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1365 err_code |= ERR_WARN;
1366
Willy Tarreau5321c422010-01-28 20:35:13 +01001367 if (cond_start &&
1368 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001369 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1370 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1371 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001372 err_code |= ERR_ALERT | ERR_FATAL;
1373 goto err;
1374 }
1375 }
1376 else if (cond_start && **cond_start) {
1377 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1378 file, line, cmd, *cond_start);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto err;
1381 }
1382
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001383 err_code |= warnif_cond_conflicts(cond,
1384 (dir == SMP_OPT_DIR_REQ) ?
1385 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1386 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1387 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001388
Willy Tarreauade5ec42010-01-28 19:33:49 +01001389 preg = calloc(1, sizeof(regex_t));
1390 if (!preg) {
1391 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1392 err_code = ERR_ALERT | ERR_FATAL;
1393 goto err;
1394 }
1395
1396 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1397 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1398 err_code = ERR_ALERT | ERR_FATAL;
1399 goto err;
1400 }
1401
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001402 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001403 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001404 if (repl && err) {
1405 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1406 file, line, cmd, *err);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 goto err;
1409 }
1410
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001411 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001412 err_code |= ERR_WARN;
1413
Willy Tarreauf4068b62012-05-08 17:37:49 +02001414 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001415 return err_code;
1416 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001417 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001418 free(preg);
1419 return err_code;
1420}
1421
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001424 * Returns the error code, 0 if OK, or any combination of :
1425 * - ERR_ABORT: must abort ASAP
1426 * - ERR_FATAL: we can continue parsing but not start the service
1427 * - ERR_WARN: a warning has been emitted
1428 * - ERR_ALERT: an alert has been emitted
1429 * Only the two first ones can stop processing, the two others are just
1430 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001432int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1433{
1434 static struct peers *curpeers = NULL;
1435 struct peer *newpeer = NULL;
1436 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001437 struct bind_conf *bind_conf;
1438 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001439 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001440 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001441
1442 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001443 if (!*args[1]) {
1444 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001448
1449 err = invalid_char(args[1]);
1450 if (err) {
1451 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1452 file, linenum, *err, args[0], args[1]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001454 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001455 }
1456
1457 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1458 /*
1459 * If there are two proxies with the same name only following
1460 * combinations are allowed:
1461 */
1462 if (strcmp(curpeers->id, args[1]) == 0) {
1463 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1464 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1465 err_code |= ERR_WARN;
1466 }
1467 }
1468
1469 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1471 err_code |= ERR_ALERT | ERR_ABORT;
1472 goto out;
1473 }
1474
1475 curpeers->next = peers;
1476 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001477 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001478 curpeers->conf.line = linenum;
1479 curpeers->last_change = now.tv_sec;
1480 curpeers->id = strdup(args[1]);
1481 }
1482 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001483 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001484 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001485 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001486
1487 if (!*args[2]) {
1488 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1489 file, linenum, args[0]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 err = invalid_char(args[1]);
1495 if (err) {
1496 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1497 file, linenum, *err, args[1]);
1498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1503 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1504 err_code |= ERR_ALERT | ERR_ABORT;
1505 goto out;
1506 }
1507
1508 /* the peers are linked backwards first */
1509 curpeers->count++;
1510 newpeer->next = curpeers->remote;
1511 curpeers->remote = newpeer;
1512 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001513 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001514 newpeer->conf.line = linenum;
1515
1516 newpeer->last_change = now.tv_sec;
1517 newpeer->id = strdup(args[1]);
1518
Willy Tarreau902636f2013-03-10 19:44:48 +01001519 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001520 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001521 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001524 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001525
1526 proto = protocol_by_family(sk->ss_family);
1527 if (!proto || !proto->connect) {
1528 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1529 file, linenum, args[0], args[1]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001533
1534 if (port1 != port2) {
1535 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1536 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
1540
Willy Tarreau2aa38802013-02-20 19:20:59 +01001541 if (!port1) {
1542 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1543 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001547
Emeric Brun32da3c42010-09-23 18:39:19 +02001548 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001549 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001550 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001551 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001552
Emeric Brun32da3c42010-09-23 18:39:19 +02001553 if (strcmp(newpeer->id, localpeer) == 0) {
1554 /* Current is local peer, it define a frontend */
1555 newpeer->local = 1;
1556
1557 if (!curpeers->peers_fe) {
1558 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1559 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1560 err_code |= ERR_ALERT | ERR_ABORT;
1561 goto out;
1562 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001563
Willy Tarreau237250c2011-07-29 01:49:03 +02001564 init_new_proxy(curpeers->peers_fe);
1565 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001566
1567 curpeers->peers_fe->last_change = now.tv_sec;
1568 curpeers->peers_fe->id = strdup(args[1]);
1569 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001570 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001571 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1572 curpeers->peers_fe->timeout.connect = 5000;
1573 curpeers->peers_fe->accept = peer_accept;
1574 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001575 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1576 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001577
1578 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1579
Willy Tarreau902636f2013-03-10 19:44:48 +01001580 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1581 if (errmsg && *errmsg) {
1582 indent_msg(&errmsg, 2);
1583 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001584 }
1585 else
1586 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1587 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001588 err_code |= ERR_FATAL;
1589 goto out;
1590 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001591
1592 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1593 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1594 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1595 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1596 l->accept = session_accept;
1597 l->handler = process_session;
1598 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1599 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1600 global.maxsock += l->maxconn;
1601 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001602 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001603 else {
1604 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1605 file, linenum, args[0], args[1],
1606 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1607 err_code |= ERR_FATAL;
1608 goto out;
1609 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001610 }
1611 } /* neither "peer" nor "peers" */
1612 else if (*args[0] != 0) {
1613 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1614 err_code |= ERR_ALERT | ERR_FATAL;
1615 goto out;
1616 }
1617
1618out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001619 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001620 return err_code;
1621}
1622
1623
Willy Tarreau3842f002009-06-14 11:39:52 +02001624int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625{
1626 static struct proxy *curproxy = NULL;
1627 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001628 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001629 int rc;
1630 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001631 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001632 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001633 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001634 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001635 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636
Willy Tarreau977b8e42006-12-29 14:19:17 +01001637 if (!strcmp(args[0], "listen"))
1638 rc = PR_CAP_LISTEN;
1639 else if (!strcmp(args[0], "frontend"))
1640 rc = PR_CAP_FE | PR_CAP_RS;
1641 else if (!strcmp(args[0], "backend"))
1642 rc = PR_CAP_BE | PR_CAP_RS;
1643 else if (!strcmp(args[0], "ruleset"))
1644 rc = PR_CAP_RS;
1645 else
1646 rc = PR_CAP_NONE;
1647
1648 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 if (!*args[1]) {
1650 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1651 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_ABORT;
1654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001656
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001657 err = invalid_char(args[1]);
1658 if (err) {
1659 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1660 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001661 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001662 }
1663
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001664 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1665 /*
1666 * If there are two proxies with the same name only following
1667 * combinations are allowed:
1668 *
1669 * listen backend frontend ruleset
1670 * listen - - - -
1671 * backend - - OK -
1672 * frontend - OK - -
1673 * ruleset - - - -
1674 */
1675
1676 if (!strcmp(curproxy->id, args[1]) &&
1677 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1678 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001679 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1680 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1681 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001682 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001683 }
1684 }
1685
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1687 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_ABORT;
1689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001691
Willy Tarreau97cb7802010-01-03 20:23:58 +01001692 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693 curproxy->next = proxy;
1694 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001695 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1696 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001697 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001699 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700
1701 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001703 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001704
Willy Tarreau4348fad2012-09-20 16:48:07 +02001705 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1706
Willy Tarreau902636f2013-03-10 19:44:48 +01001707 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1708 if (errmsg && *errmsg) {
1709 indent_msg(&errmsg, 2);
1710 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001711 }
1712 else
1713 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1714 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001715 err_code |= ERR_FATAL;
1716 goto out;
1717 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001718
Willy Tarreau4348fad2012-09-20 16:48:07 +02001719 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001720 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 }
1723
1724 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001725 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001726 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001727
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001730 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001731 curproxy->no_options = defproxy.no_options;
1732 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001733 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001734 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001735 curproxy->except_net = defproxy.except_net;
1736 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001737 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001738 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001740 if (defproxy.fwdfor_hdr_len) {
1741 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1742 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1743 }
1744
Willy Tarreaub86db342009-11-30 11:50:16 +01001745 if (defproxy.orgto_hdr_len) {
1746 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1747 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1748 }
1749
Mark Lamourinec2247f02012-01-04 13:02:01 -05001750 if (defproxy.server_id_hdr_len) {
1751 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1752 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1753 }
1754
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 if (curproxy->cap & PR_CAP_FE) {
1756 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001757 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001758 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001759
1760 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001761 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1762 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763
1764 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766
Willy Tarreau977b8e42006-12-29 14:19:17 +01001767 if (curproxy->cap & PR_CAP_BE) {
1768 curproxy->fullconn = defproxy.fullconn;
1769 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001771 if (defproxy.check_req) {
1772 curproxy->check_req = calloc(1, defproxy.check_len);
1773 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1774 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001775 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001777 if (defproxy.expect_str) {
1778 curproxy->expect_str = strdup(defproxy.expect_str);
1779 if (defproxy.expect_regex) {
1780 /* note: this regex is known to be valid */
1781 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1782 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1783 }
1784 }
1785
Willy Tarreau67402132012-05-31 20:40:20 +02001786 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 if (defproxy.cookie_name)
1788 curproxy->cookie_name = strdup(defproxy.cookie_name);
1789 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001790 if (defproxy.cookie_domain)
1791 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001792
Willy Tarreau31936852010-10-06 16:59:56 +02001793 if (defproxy.cookie_maxidle)
1794 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1795
1796 if (defproxy.cookie_maxlife)
1797 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1798
Emeric Brun647caf12009-06-30 17:57:00 +02001799 if (defproxy.rdp_cookie_name)
1800 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1801 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1802
Willy Tarreau01732802007-11-01 22:48:15 +01001803 if (defproxy.url_param_name)
1804 curproxy->url_param_name = strdup(defproxy.url_param_name);
1805 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001806
Benoitaffb4812009-03-25 13:02:10 +01001807 if (defproxy.hh_name)
1808 curproxy->hh_name = strdup(defproxy.hh_name);
1809 curproxy->hh_len = defproxy.hh_len;
1810 curproxy->hh_match_domain = defproxy.hh_match_domain;
1811
Willy Tarreauef9a3602012-12-08 22:29:20 +01001812 if (defproxy.conn_src.iface_name)
1813 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1814 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001815 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001816#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001817 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001818#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001820
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001821 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001822 if (defproxy.capture_name)
1823 curproxy->capture_name = strdup(defproxy.capture_name);
1824 curproxy->capture_namelen = defproxy.capture_namelen;
1825 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001826 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827
Willy Tarreau977b8e42006-12-29 14:19:17 +01001828 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001829 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001830 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001831 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001832 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833 curproxy->uri_auth = defproxy.uri_auth;
1834 curproxy->mon_net = defproxy.mon_net;
1835 curproxy->mon_mask = defproxy.mon_mask;
1836 if (defproxy.monitor_uri)
1837 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1838 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001839 if (defproxy.defbe.name)
1840 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001841
1842 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001843 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1844 if (curproxy->conf.logformat_string &&
1845 curproxy->conf.logformat_string != default_http_log_format &&
1846 curproxy->conf.logformat_string != default_tcp_log_format &&
1847 curproxy->conf.logformat_string != clf_http_log_format)
1848 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1849
1850 if (defproxy.conf.lfs_file) {
1851 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1852 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1853 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854 }
1855
1856 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001857 curproxy->timeout.connect = defproxy.timeout.connect;
1858 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001859 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001860 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001861 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001862 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001863 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001864 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001865 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001866 }
1867
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001869
1870 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001871 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001872 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001873 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001874 LIST_INIT(&node->list);
1875 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1876 }
1877
Willy Tarreau62a61232013-04-12 18:13:46 +02001878 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1879 if (curproxy->conf.uniqueid_format_string)
1880 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1881
1882 if (defproxy.conf.uif_file) {
1883 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1884 curproxy->conf.uif_line = defproxy.conf.uif_line;
1885 }
William Lallemanda73203e2012-03-12 12:48:57 +01001886
1887 /* copy default header unique id */
1888 if (defproxy.header_unique_id)
1889 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1890
William Lallemand82fe75c2012-10-23 10:25:10 +02001891 /* default compression options */
1892 if (defproxy.comp != NULL) {
1893 curproxy->comp = calloc(1, sizeof(struct comp));
1894 curproxy->comp->algos = defproxy.comp->algos;
1895 curproxy->comp->types = defproxy.comp->types;
1896 }
1897
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001899 curproxy->conf.used_listener_id = EB_ROOT;
1900 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001901
Willy Tarreau93893792009-07-23 13:19:11 +02001902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 }
1904 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1905 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001906 /* FIXME-20070101: we should do this too at the end of the
1907 * config parsing to free all default values.
1908 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001909 free(defproxy.check_req);
1910 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001911 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001912 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001913 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001914 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001915 free(defproxy.capture_name);
1916 free(defproxy.monitor_uri);
1917 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001918 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001919 free(defproxy.fwdfor_hdr_name);
1920 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001921 free(defproxy.orgto_hdr_name);
1922 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001923 free(defproxy.server_id_hdr_name);
1924 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001925 free(defproxy.expect_str);
1926 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001927
Willy Tarreau62a61232013-04-12 18:13:46 +02001928 if (defproxy.conf.logformat_string != default_http_log_format &&
1929 defproxy.conf.logformat_string != default_tcp_log_format &&
1930 defproxy.conf.logformat_string != clf_http_log_format)
1931 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001932
Willy Tarreau62a61232013-04-12 18:13:46 +02001933 free(defproxy.conf.uniqueid_format_string);
1934 free(defproxy.conf.lfs_file);
1935 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001936
Willy Tarreaua534fea2008-08-03 12:19:50 +02001937 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001938 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001939
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 /* we cannot free uri_auth because it might already be used */
1941 init_default_instance();
1942 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001943 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1944 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001945 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 }
1948 else if (curproxy == NULL) {
1949 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001953
1954 /* update the current file and line being parsed */
1955 curproxy->conf.args.file = curproxy->conf.file;
1956 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001957
1958 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001960 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001961 int cur_arg;
1962
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963 if (curproxy == &defproxy) {
1964 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_ALERT | ERR_FATAL;
1966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001968 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001969 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970
Willy Tarreau24709282013-03-10 21:32:12 +01001971 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001972 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001977
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001978 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001979
1980 /* use default settings for unix sockets */
1981 bind_conf->ux.uid = global.unix_bind.ux.uid;
1982 bind_conf->ux.gid = global.unix_bind.ux.gid;
1983 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001984
1985 /* NOTE: the following line might create several listeners if there
1986 * are comma-separated IPs or port ranges. So all further processing
1987 * will have to be applied to all listeners created after last_listen.
1988 */
Willy Tarreau902636f2013-03-10 19:44:48 +01001989 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
1990 if (errmsg && *errmsg) {
1991 indent_msg(&errmsg, 2);
1992 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001993 }
1994 else
1995 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1996 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001997 err_code |= ERR_ALERT | ERR_FATAL;
1998 goto out;
1999 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002000
Willy Tarreau4348fad2012-09-20 16:48:07 +02002001 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2002 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002003 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002004 }
2005
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002006 cur_arg = 2;
2007 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002008 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002009 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002010 char *err;
2011
Willy Tarreau26982662012-09-12 23:17:10 +02002012 kw = bind_find_kw(args[cur_arg]);
2013 if (kw) {
2014 char *err = NULL;
2015 int code;
2016
2017 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002018 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2019 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002020 cur_arg += 1 + kw->skip ;
2021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
2023 }
2024
Willy Tarreau4348fad2012-09-20 16:48:07 +02002025 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002026 err_code |= code;
2027
2028 if (code) {
2029 if (err && *err) {
2030 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002031 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002032 }
2033 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002034 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2035 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002036 if (code & ERR_FATAL) {
2037 free(err);
2038 cur_arg += 1 + kw->skip;
2039 goto out;
2040 }
2041 }
2042 free(err);
2043 cur_arg += 1 + kw->skip;
2044 continue;
2045 }
2046
Willy Tarreau8638f482012-09-18 18:01:17 +02002047 err = NULL;
2048 if (!bind_dumped) {
2049 bind_dump_kws(&err);
2050 indent_msg(&err, 4);
2051 bind_dumped = 1;
2052 }
2053
2054 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2055 file, linenum, args[0], args[1], args[cur_arg],
2056 err ? " Registered keywords :" : "", err ? err : "");
2057 free(err);
2058
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002061 }
Willy Tarreau93893792009-07-23 13:19:11 +02002062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 }
2064 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2065 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2066 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_ALERT | ERR_FATAL;
2069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002070 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002071 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002073
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 /* flush useless bits */
2075 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002078 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002080 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002081
Willy Tarreau1c47f852006-07-09 08:22:27 +02002082 if (!*args[1]) {
2083 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2084 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002087 }
2088
Willy Tarreaua534fea2008-08-03 12:19:50 +02002089 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002090 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002091 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002092 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002093 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2094
Willy Tarreau93893792009-07-23 13:19:11 +02002095 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2098 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2099 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2100 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2101 else {
2102 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
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 }
2106 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002107 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002108 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002109
2110 if (curproxy == &defproxy) {
2111 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2112 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002115 }
2116
2117 if (!*args[1]) {
2118 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2119 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002122 }
2123
2124 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002125 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002126
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002127 if (curproxy->uuid <= 0) {
2128 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002129 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_ALERT | ERR_FATAL;
2131 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002132 }
2133
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002134 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2135 if (node) {
2136 struct proxy *target = container_of(node, struct proxy, conf.id);
2137 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2138 file, linenum, proxy_type_str(curproxy), curproxy->id,
2139 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2140 err_code |= ERR_ALERT | ERR_FATAL;
2141 goto out;
2142 }
2143 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002144 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002145 else if (!strcmp(args[0], "description")) {
2146 int i, len=0;
2147 char *d;
2148
Cyril Bonté99ed3272010-01-24 23:29:44 +01002149 if (curproxy == &defproxy) {
2150 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2151 file, linenum, args[0]);
2152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
2154 }
2155
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002156 if (!*args[1]) {
2157 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2158 file, linenum, args[0]);
2159 return -1;
2160 }
2161
2162 for(i=1; *args[i]; i++)
2163 len += strlen(args[i])+1;
2164
2165 d = (char *)calloc(1, len);
2166 curproxy->desc = d;
2167
2168 d += sprintf(d, "%s", args[1]);
2169 for(i=2; *args[i]; i++)
2170 d += sprintf(d, " %s", args[i]);
2171
2172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2174 curproxy->state = PR_STSTOPPED;
2175 }
2176 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2177 curproxy->state = PR_STNEW;
2178 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002179 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2180 int cur_arg = 1;
2181 unsigned int set = 0;
2182
2183 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002184 unsigned int low, high;
2185
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002186 if (strcmp(args[cur_arg], "all") == 0) {
2187 set = 0;
2188 break;
2189 }
2190 else if (strcmp(args[cur_arg], "odd") == 0) {
2191 set |= 0x55555555;
2192 }
2193 else if (strcmp(args[cur_arg], "even") == 0) {
2194 set |= 0xAAAAAAAA;
2195 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002196 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002197 char *dash = strchr(args[cur_arg], '-');
2198
2199 low = high = str2uic(args[cur_arg]);
2200 if (dash)
2201 high = str2uic(dash + 1);
2202
2203 if (high < low) {
2204 unsigned int swap = low;
2205 low = high;
2206 high = swap;
2207 }
2208
2209 if (low < 1 || high > 32) {
2210 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002211 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002214 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002215
2216 if (high > global.nbproc) {
2217 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2218 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002220 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002221 while (low <= high)
2222 set |= 1 << (low++ - 1);
2223 }
2224 else {
2225 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2226 file, linenum, args[0]);
2227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002229 }
2230 cur_arg++;
2231 }
2232 curproxy->bind_proc = set;
2233 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002234 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002235 if (curproxy == &defproxy) {
2236 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002239 }
2240
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002241 err = invalid_char(args[1]);
2242 if (err) {
2243 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2244 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002245 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002246 }
2247
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002248 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002249 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2250 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002253 }
2254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2256 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257
Willy Tarreau977b8e42006-12-29 14:19:17 +01002258 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002260
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 if (*(args[1]) == 0) {
2262 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2263 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002267
Willy Tarreau67402132012-05-31 20:40:20 +02002268 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002269 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002270 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002271 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 curproxy->cookie_name = strdup(args[1]);
2273 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002274
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 cur_arg = 2;
2276 while (*(args[cur_arg])) {
2277 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002278 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }
2280 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002281 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 }
2283 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002284 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 }
2286 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002287 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 }
2289 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002290 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002292 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002293 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002296 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002298 else if (!strcmp(args[cur_arg], "httponly")) {
2299 curproxy->ck_opts |= PR_CK_HTTPONLY;
2300 }
2301 else if (!strcmp(args[cur_arg], "secure")) {
2302 curproxy->ck_opts |= PR_CK_SECURE;
2303 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002304 else if (!strcmp(args[cur_arg], "domain")) {
2305 if (!*args[cur_arg + 1]) {
2306 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2307 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002310 }
2311
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002312 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002313 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002314 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2315 " dots nor does not start with a dot."
2316 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002317 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002318 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002319 }
2320
2321 err = invalid_domainchar(args[cur_arg + 1]);
2322 if (err) {
2323 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2324 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002327 }
2328
Willy Tarreau68a897b2009-12-03 23:28:34 +01002329 if (!curproxy->cookie_domain) {
2330 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2331 } else {
2332 /* one domain was already specified, add another one by
2333 * building the string which will be returned along with
2334 * the cookie.
2335 */
2336 char *new_ptr;
2337 int new_len = strlen(curproxy->cookie_domain) +
2338 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2339 new_ptr = malloc(new_len);
2340 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2341 free(curproxy->cookie_domain);
2342 curproxy->cookie_domain = new_ptr;
2343 }
Willy Tarreau31936852010-10-06 16:59:56 +02002344 cur_arg++;
2345 }
2346 else if (!strcmp(args[cur_arg], "maxidle")) {
2347 unsigned int maxidle;
2348 const char *res;
2349
2350 if (!*args[cur_arg + 1]) {
2351 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2352 file, linenum, args[cur_arg]);
2353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
2355 }
2356
2357 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2358 if (res) {
2359 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2360 file, linenum, *res, args[cur_arg]);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364 curproxy->cookie_maxidle = maxidle;
2365 cur_arg++;
2366 }
2367 else if (!strcmp(args[cur_arg], "maxlife")) {
2368 unsigned int maxlife;
2369 const char *res;
2370
2371 if (!*args[cur_arg + 1]) {
2372 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2373 file, linenum, args[cur_arg]);
2374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
2376 }
2377
2378 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2379 if (res) {
2380 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2381 file, linenum, *res, args[cur_arg]);
2382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
2384 }
2385 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002386 cur_arg++;
2387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002389 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 +02002390 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394 cur_arg++;
2395 }
Willy Tarreau67402132012-05-31 20:40:20 +02002396 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2398 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401
Willy Tarreau67402132012-05-31 20:40:20 +02002402 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2404 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002407
Willy Tarreau67402132012-05-31 20:40:20 +02002408 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002409 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2410 file, linenum);
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002414 else if (!strcmp(args[0], "persist")) { /* persist */
2415 if (*(args[1]) == 0) {
2416 Alert("parsing [%s:%d] : missing persist method.\n",
2417 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002420 }
2421
2422 if (!strncmp(args[1], "rdp-cookie", 10)) {
2423 curproxy->options2 |= PR_O2_RDPC_PRST;
2424
Emeric Brunb982a3d2010-01-04 15:45:53 +01002425 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002426 const char *beg, *end;
2427
2428 beg = args[1] + 11;
2429 end = strchr(beg, ')');
2430
2431 if (!end || end == beg) {
2432 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2433 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002436 }
2437
2438 free(curproxy->rdp_cookie_name);
2439 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2440 curproxy->rdp_cookie_len = end-beg;
2441 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002442 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002443 free(curproxy->rdp_cookie_name);
2444 curproxy->rdp_cookie_name = strdup("msts");
2445 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2446 }
2447 else { /* syntax */
2448 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2449 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002452 }
2453 }
2454 else {
2455 Alert("parsing [%s:%d] : unknown persist method.\n",
2456 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002459 }
2460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002462 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002464 if (curproxy == &defproxy) {
2465 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
2469
Willy Tarreau977b8e42006-12-29 14:19:17 +01002470 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002472
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002474 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 }
2479 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002480 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 curproxy->appsession_name = strdup(args[1]);
2482 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2483 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002484 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2485 if (err) {
2486 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2487 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002490 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002491 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002492
Willy Tarreau51041c72007-09-09 21:56:53 +02002493 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2494 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002495 err_code |= ERR_ALERT | ERR_ABORT;
2496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002498
2499 cur_arg = 6;
2500 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002501 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2502 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002503 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002504 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002505 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002506 } else if (!strcmp(args[cur_arg], "prefix")) {
2507 curproxy->options2 |= PR_O2_AS_PFX;
2508 } else if (!strcmp(args[cur_arg], "mode")) {
2509 if (!*args[cur_arg + 1]) {
2510 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2511 file, linenum, args[0], args[cur_arg]);
2512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
2514 }
2515
2516 cur_arg++;
2517 if (!strcmp(args[cur_arg], "query-string")) {
2518 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2519 curproxy->options2 |= PR_O2_AS_M_QS;
2520 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2521 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2522 curproxy->options2 |= PR_O2_AS_M_PP;
2523 } else {
2524 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
2527 }
2528 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002529 cur_arg++;
2530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 } /* Url App Session */
2532 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002533 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002535
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002537 if (curproxy == &defproxy) {
2538 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
2541 }
2542
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 if (*(args[4]) == 0) {
2544 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2545 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002549 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 curproxy->capture_name = strdup(args[2]);
2551 curproxy->capture_namelen = strlen(curproxy->capture_name);
2552 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 curproxy->to_log |= LW_COOKIE;
2554 }
2555 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2556 struct cap_hdr *hdr;
2557
2558 if (curproxy == &defproxy) {
2559 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 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 }
2563
2564 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2565 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2566 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
2570
2571 hdr = calloc(sizeof(struct cap_hdr), 1);
2572 hdr->next = curproxy->req_cap;
2573 hdr->name = strdup(args[3]);
2574 hdr->namelen = strlen(args[3]);
2575 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002576 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 hdr->index = curproxy->nb_req_cap++;
2578 curproxy->req_cap = hdr;
2579 curproxy->to_log |= LW_REQHDR;
2580 }
2581 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2582 struct cap_hdr *hdr;
2583
2584 if (curproxy == &defproxy) {
2585 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 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
2589
2590 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2591 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2592 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596 hdr = calloc(sizeof(struct cap_hdr), 1);
2597 hdr->next = curproxy->rsp_cap;
2598 hdr->name = strdup(args[3]);
2599 hdr->namelen = strlen(args[3]);
2600 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002601 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 hdr->index = curproxy->nb_rsp_cap++;
2603 curproxy->rsp_cap = hdr;
2604 curproxy->to_log |= LW_RSPHDR;
2605 }
2606 else {
2607 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2608 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 }
2612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002614 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002616
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 if (*(args[1]) == 0) {
2618 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
2623 curproxy->conn_retries = atol(args[1]);
2624 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002625 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002626 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002627
2628 if (curproxy == &defproxy) {
2629 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
2633
Willy Tarreau20b0de52012-12-24 15:45:22 +01002634 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2635 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2636 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2637 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002638 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002639 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2640 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 +01002641 file, linenum, args[0]);
2642 err_code |= ERR_WARN;
2643 }
2644
Willy Tarreauff011f22011-01-06 17:51:27 +01002645 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002646
Willy Tarreauff011f22011-01-06 17:51:27 +01002647 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002648 err_code |= ERR_ALERT | ERR_ABORT;
2649 goto out;
2650 }
2651
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002652 err_code |= warnif_cond_conflicts(rule->cond,
2653 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2654 file, linenum);
2655
Willy Tarreauff011f22011-01-06 17:51:27 +01002656 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002657 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002658 else if (!strcmp(args[0], "http-response")) { /* response access control */
2659 struct http_res_rule *rule;
2660
2661 if (curproxy == &defproxy) {
2662 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666
2667 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2668 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2669 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2670 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2671 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2672 file, linenum, args[0]);
2673 err_code |= ERR_WARN;
2674 }
2675
2676 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2677
2678 if (!rule) {
2679 err_code |= ERR_ALERT | ERR_ABORT;
2680 goto out;
2681 }
2682
2683 err_code |= warnif_cond_conflicts(rule->cond,
2684 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2685 file, linenum);
2686
2687 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2688 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002689 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2690 /* set the header name and length into the proxy structure */
2691 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2692 err_code |= ERR_WARN;
2693
2694 if (!*args[1]) {
2695 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2696 file, linenum, args[0]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700
2701 /* set the desired header name */
2702 free(curproxy->server_id_hdr_name);
2703 curproxy->server_id_hdr_name = strdup(args[1]);
2704 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2705 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002706 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002707 if (curproxy == &defproxy) {
2708 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002709 err_code |= ERR_ALERT | ERR_FATAL;
2710 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002711 }
2712
Willy Tarreauef6494c2010-01-28 17:12:36 +01002713 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002714 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002718 }
2719
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002720 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2721 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2722 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002725 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002726
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002727 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002728 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002729 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002730 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002731 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002732
Cyril Bonté99ed3272010-01-24 23:29:44 +01002733 if (curproxy == &defproxy) {
2734 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
2737 }
2738
Willy Tarreau4baae242012-12-27 12:00:31 +01002739 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2740 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2741 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002744 }
2745
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002746 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002747 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002748 err_code |= warnif_cond_conflicts(rule->cond,
2749 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2750 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002751 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002752 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002753 struct switching_rule *rule;
2754
Willy Tarreaub099aca2008-10-12 17:26:37 +02002755 if (curproxy == &defproxy) {
2756 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002759 }
2760
Willy Tarreau55ea7572007-06-17 19:56:27 +02002761 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002763
2764 if (*(args[1]) == 0) {
2765 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002768 }
2769
Willy Tarreauef6494c2010-01-28 17:12:36 +01002770 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002771 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2772 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002775 }
2776
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002777 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2778 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2779 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002782 }
2783
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002784 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002785
Willy Tarreau55ea7572007-06-17 19:56:27 +02002786 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2787 rule->cond = cond;
2788 rule->be.name = strdup(args[1]);
2789 LIST_INIT(&rule->list);
2790 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2791 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002792 else if (strcmp(args[0], "use-server") == 0) {
2793 struct server_rule *rule;
2794
2795 if (curproxy == &defproxy) {
2796 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
2799 }
2800
2801 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2802 err_code |= ERR_WARN;
2803
2804 if (*(args[1]) == 0) {
2805 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
2808 }
2809
2810 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2811 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2812 file, linenum, args[0]);
2813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
2815 }
2816
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002817 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2818 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2819 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
2822 }
2823
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002824 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002825
2826 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2827 rule->cond = cond;
2828 rule->srv.name = strdup(args[1]);
2829 LIST_INIT(&rule->list);
2830 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2831 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2832 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002833 else if ((!strcmp(args[0], "force-persist")) ||
2834 (!strcmp(args[0], "ignore-persist"))) {
2835 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002836
2837 if (curproxy == &defproxy) {
2838 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
2841 }
2842
2843 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2844 err_code |= ERR_WARN;
2845
Willy Tarreauef6494c2010-01-28 17:12:36 +01002846 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002847 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2848 file, linenum, args[0]);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851 }
2852
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002853 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2854 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2855 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
2859
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002860 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2861 * where force-persist is applied.
2862 */
2863 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002864
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002865 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002866 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002867 if (!strcmp(args[0], "force-persist")) {
2868 rule->type = PERSIST_TYPE_FORCE;
2869 } else {
2870 rule->type = PERSIST_TYPE_IGNORE;
2871 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002872 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002873 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002874 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002875 else if (!strcmp(args[0], "stick-table")) {
2876 int myidx = 1;
2877
Emeric Brun32da3c42010-09-23 18:39:19 +02002878 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002879 curproxy->table.type = (unsigned int)-1;
2880 while (*args[myidx]) {
2881 const char *err;
2882
2883 if (strcmp(args[myidx], "size") == 0) {
2884 myidx++;
2885 if (!*(args[myidx])) {
2886 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2887 file, linenum, args[myidx-1]);
2888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
2891 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2892 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2893 file, linenum, *err, args[myidx-1]);
2894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002897 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002898 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002899 else if (strcmp(args[myidx], "peers") == 0) {
2900 myidx++;
2901 if (!*(args[myidx])) {
2902 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2903 file, linenum, args[myidx-1]);
2904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
2906 }
2907 curproxy->table.peers.name = strdup(args[myidx++]);
2908 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002909 else if (strcmp(args[myidx], "expire") == 0) {
2910 myidx++;
2911 if (!*(args[myidx])) {
2912 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2913 file, linenum, args[myidx-1]);
2914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
2916 }
2917 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2918 if (err) {
2919 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2920 file, linenum, *err, args[myidx-1]);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923 }
2924 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002925 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002926 }
2927 else if (strcmp(args[myidx], "nopurge") == 0) {
2928 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002929 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002930 }
2931 else if (strcmp(args[myidx], "type") == 0) {
2932 myidx++;
2933 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2934 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2935 file, linenum, args[myidx]);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002939 /* myidx already points to next arg */
2940 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002941 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002942 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002943 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002944
2945 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002946 nw = args[myidx];
2947 while (*nw) {
2948 /* the "store" keyword supports a comma-separated list */
2949 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002950 sa = NULL; /* store arg */
2951 while (*nw && *nw != ',') {
2952 if (*nw == '(') {
2953 *nw = 0;
2954 sa = ++nw;
2955 while (*nw != ')') {
2956 if (!*nw) {
2957 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2958 file, linenum, args[0], cw);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
2961 }
2962 nw++;
2963 }
2964 *nw = '\0';
2965 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002966 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002967 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002968 if (*nw)
2969 *nw++ = '\0';
2970 type = stktable_get_data_type(cw);
2971 if (type < 0) {
2972 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2973 file, linenum, args[0], cw);
2974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
2976 }
Willy Tarreauac782882010-06-20 10:41:54 +02002977
2978 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2979 switch (err) {
2980 case PE_NONE: break;
2981 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002982 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2983 file, linenum, args[0], cw);
2984 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002985 break;
2986
2987 case PE_ARG_MISSING:
2988 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2989 file, linenum, args[0], cw);
2990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
2992
2993 case PE_ARG_NOT_USED:
2994 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2995 file, linenum, args[0], cw);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998
2999 default:
3000 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3001 file, linenum, args[0], cw);
3002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003004 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003005 }
3006 myidx++;
3007 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003008 else {
3009 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3010 file, linenum, args[myidx]);
3011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003013 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003014 }
3015
3016 if (!curproxy->table.size) {
3017 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3018 file, linenum);
3019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021 }
3022
3023 if (curproxy->table.type == (unsigned int)-1) {
3024 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3025 file, linenum);
3026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
3028 }
3029 }
3030 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003031 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003032 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003033 int myidx = 0;
3034 const char *name = NULL;
3035 int flags;
3036
3037 if (curproxy == &defproxy) {
3038 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
3041 }
3042
3043 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3044 err_code |= ERR_WARN;
3045 goto out;
3046 }
3047
3048 myidx++;
3049 if ((strcmp(args[myidx], "store") == 0) ||
3050 (strcmp(args[myidx], "store-request") == 0)) {
3051 myidx++;
3052 flags = STK_IS_STORE;
3053 }
3054 else if (strcmp(args[myidx], "store-response") == 0) {
3055 myidx++;
3056 flags = STK_IS_STORE | STK_ON_RSP;
3057 }
3058 else if (strcmp(args[myidx], "match") == 0) {
3059 myidx++;
3060 flags = STK_IS_MATCH;
3061 }
3062 else if (strcmp(args[myidx], "on") == 0) {
3063 myidx++;
3064 flags = STK_IS_MATCH | STK_IS_STORE;
3065 }
3066 else {
3067 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
3070 }
3071
3072 if (*(args[myidx]) == 0) {
3073 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
3076 }
3077
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003078 curproxy->conf.args.ctx = ARGC_STK;
3079 expr = sample_parse_expr(args, &myidx, trash.str, trash.size, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003080 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003081 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
3084 }
3085
3086 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003087 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3088 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3089 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003090 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003091 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003092 goto out;
3093 }
3094 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003095 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3096 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3097 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003098 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003099 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003100 goto out;
3101 }
3102 }
3103
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003104 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003105 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003106
Emeric Brunb982a3d2010-01-04 15:45:53 +01003107 if (strcmp(args[myidx], "table") == 0) {
3108 myidx++;
3109 name = args[myidx++];
3110 }
3111
Willy Tarreauef6494c2010-01-28 17:12:36 +01003112 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003113 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3114 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3115 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003116 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003117 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003118 goto out;
3119 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003120 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003121 else if (*(args[myidx])) {
3122 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3123 file, linenum, args[0], args[myidx]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003125 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003126 goto out;
3127 }
Emeric Brun97679e72010-09-23 17:56:44 +02003128 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003129 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003130 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003131 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003132
Emeric Brunb982a3d2010-01-04 15:45:53 +01003133 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3134 rule->cond = cond;
3135 rule->expr = expr;
3136 rule->flags = flags;
3137 rule->table.name = name ? strdup(name) : NULL;
3138 LIST_INIT(&rule->list);
3139 if (flags & STK_ON_RSP)
3140 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3141 else
3142 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003145 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003146 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003147
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3149 curproxy->uri_auth = NULL; /* we must detach from the default config */
3150
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003151 if (!*args[1]) {
3152 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003153 } else if (!strcmp(args[1], "admin")) {
3154 struct stats_admin_rule *rule;
3155
3156 if (curproxy == &defproxy) {
3157 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3158 err_code |= ERR_ALERT | ERR_FATAL;
3159 goto out;
3160 }
3161
3162 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3163 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3164 err_code |= ERR_ALERT | ERR_ABORT;
3165 goto out;
3166 }
3167
3168 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3169 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3170 file, linenum, args[0], args[1]);
3171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
3173 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003174 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3175 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3176 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
3179 }
3180
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003181 err_code |= warnif_cond_conflicts(cond,
3182 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3183 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003184
3185 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3186 rule->cond = cond;
3187 LIST_INIT(&rule->list);
3188 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 } else if (!strcmp(args[1], "uri")) {
3190 if (*(args[2]) == 0) {
3191 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3195 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_ABORT;
3197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 }
3199 } else if (!strcmp(args[1], "realm")) {
3200 if (*(args[2]) == 0) {
3201 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3205 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_ABORT;
3207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003209 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003210 unsigned interval;
3211
3212 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3213 if (err) {
3214 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3215 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003218 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3219 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_ABORT;
3221 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003222 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003223 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003224 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003225
3226 if (curproxy == &defproxy) {
3227 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
3230 }
3231
3232 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3233 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3234 err_code |= ERR_ALERT | ERR_ABORT;
3235 goto out;
3236 }
3237
Willy Tarreauff011f22011-01-06 17:51:27 +01003238 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3239 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003240 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3241 file, linenum, args[0]);
3242 err_code |= ERR_WARN;
3243 }
3244
Willy Tarreauff011f22011-01-06 17:51:27 +01003245 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003246
Willy Tarreauff011f22011-01-06 17:51:27 +01003247 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003248 err_code |= ERR_ALERT | ERR_ABORT;
3249 goto out;
3250 }
3251
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003252 err_code |= warnif_cond_conflicts(rule->cond,
3253 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3254 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003255 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003256
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 } else if (!strcmp(args[1], "auth")) {
3258 if (*(args[2]) == 0) {
3259 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3263 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_ABORT;
3265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 }
3267 } else if (!strcmp(args[1], "scope")) {
3268 if (*(args[2]) == 0) {
3269 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3273 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_ABORT;
3275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
3277 } else if (!strcmp(args[1], "enable")) {
3278 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3279 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_ABORT;
3281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003283 } else if (!strcmp(args[1], "hide-version")) {
3284 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3285 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003286 err_code |= ERR_ALERT | ERR_ABORT;
3287 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003288 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003289 } else if (!strcmp(args[1], "show-legends")) {
3290 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3291 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3292 err_code |= ERR_ALERT | ERR_ABORT;
3293 goto out;
3294 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003295 } else if (!strcmp(args[1], "show-node")) {
3296
3297 if (*args[2]) {
3298 int i;
3299 char c;
3300
3301 for (i=0; args[2][i]; i++) {
3302 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003303 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3304 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003305 break;
3306 }
3307
3308 if (!i || args[2][i]) {
3309 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3310 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3311 file, linenum, args[0], args[1]);
3312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
3314 }
3315 }
3316
3317 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3318 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3319 err_code |= ERR_ALERT | ERR_ABORT;
3320 goto out;
3321 }
3322 } else if (!strcmp(args[1], "show-desc")) {
3323 char *desc = NULL;
3324
3325 if (*args[2]) {
3326 int i, len=0;
3327 char *d;
3328
3329 for(i=2; *args[i]; i++)
3330 len += strlen(args[i])+1;
3331
3332 desc = d = (char *)calloc(1, len);
3333
3334 d += sprintf(d, "%s", args[2]);
3335 for(i=3; *args[i]; i++)
3336 d += sprintf(d, " %s", args[i]);
3337 }
3338
3339 if (!*args[2] && !global.desc)
3340 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3341 file, linenum, args[1]);
3342 else {
3343 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3344 free(desc);
3345 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3346 err_code |= ERR_ALERT | ERR_ABORT;
3347 goto out;
3348 }
3349 free(desc);
3350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003352stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003353 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 +01003354 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003355 err_code |= ERR_ALERT | ERR_FATAL;
3356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 }
3358 }
3359 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003360 int optnum;
3361
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003362 if (*(args[1]) == '\0') {
3363 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3364 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003368
3369 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3370 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003371 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3372 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3373 file, linenum, cfg_opts[optnum].name);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
Willy Tarreau93893792009-07-23 13:19:11 +02003377 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3378 err_code |= ERR_WARN;
3379 goto out;
3380 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003381
Willy Tarreau3842f002009-06-14 11:39:52 +02003382 curproxy->no_options &= ~cfg_opts[optnum].val;
3383 curproxy->options &= ~cfg_opts[optnum].val;
3384
3385 switch (kwm) {
3386 case KWM_STD:
3387 curproxy->options |= cfg_opts[optnum].val;
3388 break;
3389 case KWM_NO:
3390 curproxy->no_options |= cfg_opts[optnum].val;
3391 break;
3392 case KWM_DEF: /* already cleared */
3393 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003394 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003395
Willy Tarreau93893792009-07-23 13:19:11 +02003396 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003397 }
3398 }
3399
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003400 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3401 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003402 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3403 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3404 file, linenum, cfg_opts2[optnum].name);
3405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
Willy Tarreau93893792009-07-23 13:19:11 +02003408 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3409 err_code |= ERR_WARN;
3410 goto out;
3411 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003412
Willy Tarreau3842f002009-06-14 11:39:52 +02003413 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3414 curproxy->options2 &= ~cfg_opts2[optnum].val;
3415
3416 switch (kwm) {
3417 case KWM_STD:
3418 curproxy->options2 |= cfg_opts2[optnum].val;
3419 break;
3420 case KWM_NO:
3421 curproxy->no_options2 |= cfg_opts2[optnum].val;
3422 break;
3423 case KWM_DEF: /* already cleared */
3424 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003425 }
Willy Tarreau93893792009-07-23 13:19:11 +02003426 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003427 }
3428 }
3429
Willy Tarreau3842f002009-06-14 11:39:52 +02003430 if (kwm != KWM_STD) {
3431 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003432 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003435 }
3436
Emeric Brun3a058f32009-06-30 18:26:00 +02003437 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003438 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003440 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003441 if (*(args[2]) != '\0') {
3442 if (!strcmp(args[2], "clf")) {
3443 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003444 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003445 } else {
3446 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003449 }
3450 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003451 if (curproxy->conf.logformat_string != default_http_log_format &&
3452 curproxy->conf.logformat_string != default_tcp_log_format &&
3453 curproxy->conf.logformat_string != clf_http_log_format)
3454 free(curproxy->conf.logformat_string);
3455 curproxy->conf.logformat_string = logformat;
3456
3457 free(curproxy->conf.lfs_file);
3458 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3459 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003460 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003461 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003462 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003463 if (curproxy->conf.logformat_string != default_http_log_format &&
3464 curproxy->conf.logformat_string != default_tcp_log_format &&
3465 curproxy->conf.logformat_string != clf_http_log_format)
3466 free(curproxy->conf.logformat_string);
3467 curproxy->conf.logformat_string = default_tcp_log_format;
3468
3469 free(curproxy->conf.lfs_file);
3470 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3471 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 else if (!strcmp(args[1], "tcpka")) {
3474 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003475 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003476 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003477
3478 if (curproxy->cap & PR_CAP_FE)
3479 curproxy->options |= PR_O_TCP_CLI_KA;
3480 if (curproxy->cap & PR_CAP_BE)
3481 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003482 }
3483 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003484 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_WARN;
3486
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003488 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003489 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003490 curproxy->options2 &= ~PR_O2_CHK_ANY;
3491 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 if (!*args[2]) { /* no argument */
3493 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3494 curproxy->check_len = strlen(DEF_CHECK_REQ);
3495 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003496 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003497 curproxy->check_req = (char *)malloc(reqlen);
3498 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003499 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003501 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 if (*args[4])
3503 reqlen += strlen(args[4]);
3504 else
3505 reqlen += strlen("HTTP/1.0");
3506
3507 curproxy->check_req = (char *)malloc(reqlen);
3508 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003509 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003511 }
3512 else if (!strcmp(args[1], "ssl-hello-chk")) {
3513 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003514 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003516
Willy Tarreaua534fea2008-08-03 12:19:50 +02003517 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003518 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003519 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003520 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 }
Willy Tarreau23677902007-05-08 23:50:35 +02003522 else if (!strcmp(args[1], "smtpchk")) {
3523 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003524 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003525 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003526 curproxy->options2 &= ~PR_O2_CHK_ANY;
3527 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003528
3529 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3530 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3531 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3532 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3533 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3534 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3535 curproxy->check_req = (char *)malloc(reqlen);
3536 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3537 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3538 } else {
3539 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3540 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3541 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3542 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3543 }
3544 }
3545 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003546 else if (!strcmp(args[1], "lb-agent-chk")) {
3547 /* use dynmaic health check */
3548 free(curproxy->check_req);
3549 curproxy->check_req = NULL;
3550 curproxy->options2 &= ~PR_O2_CHK_ANY;
3551 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3552 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003553 else if (!strcmp(args[1], "pgsql-check")) {
3554 /* use PostgreSQL request to check servers' health */
3555 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3556 err_code |= ERR_WARN;
3557
3558 free(curproxy->check_req);
3559 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003560 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003561 curproxy->options2 |= PR_O2_PGSQL_CHK;
3562
3563 if (*(args[2])) {
3564 int cur_arg = 2;
3565
3566 while (*(args[cur_arg])) {
3567 if (strcmp(args[cur_arg], "user") == 0) {
3568 char * packet;
3569 uint32_t packet_len;
3570 uint32_t pv;
3571
3572 /* suboption header - needs additional argument for it */
3573 if (*(args[cur_arg+1]) == 0) {
3574 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3575 file, linenum, args[0], args[1], args[cur_arg]);
3576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
3578 }
3579
3580 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3581 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3582 pv = htonl(0x30000); /* protocol version 3.0 */
3583
3584 packet = (char*) calloc(1, packet_len);
3585
3586 memcpy(packet + 4, &pv, 4);
3587
3588 /* copy "user" */
3589 memcpy(packet + 8, "user", 4);
3590
3591 /* copy username */
3592 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3593
3594 free(curproxy->check_req);
3595 curproxy->check_req = packet;
3596 curproxy->check_len = packet_len;
3597
3598 packet_len = htonl(packet_len);
3599 memcpy(packet, &packet_len, 4);
3600 cur_arg += 2;
3601 } else {
3602 /* unknown suboption - catchall */
3603 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3604 file, linenum, args[0], args[1]);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
3607 }
3608 } /* end while loop */
3609 }
3610 }
3611
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003612 else if (!strcmp(args[1], "redis-check")) {
3613 /* use REDIS PING request to check servers' health */
3614 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3615 err_code |= ERR_WARN;
3616
3617 free(curproxy->check_req);
3618 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003619 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003620 curproxy->options2 |= PR_O2_REDIS_CHK;
3621
3622 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3623 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3624 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3625 }
3626
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003627 else if (!strcmp(args[1], "mysql-check")) {
3628 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003629 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3630 err_code |= ERR_WARN;
3631
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003632 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003633 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003634 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003635 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003636
3637 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3638 * const char mysql40_client_auth_pkt[] = {
3639 * "\x0e\x00\x00" // packet length
3640 * "\x01" // packet number
3641 * "\x00\x00" // client capabilities
3642 * "\x00\x00\x01" // max packet
3643 * "haproxy\x00" // username (null terminated string)
3644 * "\x00" // filler (always 0x00)
3645 * "\x01\x00\x00" // packet length
3646 * "\x00" // packet number
3647 * "\x01" // COM_QUIT command
3648 * };
3649 */
3650
3651 if (*(args[2])) {
3652 int cur_arg = 2;
3653
3654 while (*(args[cur_arg])) {
3655 if (strcmp(args[cur_arg], "user") == 0) {
3656 char *mysqluser;
3657 int packetlen, reqlen, userlen;
3658
3659 /* suboption header - needs additional argument for it */
3660 if (*(args[cur_arg+1]) == 0) {
3661 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3662 file, linenum, args[0], args[1], args[cur_arg]);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
3666 mysqluser = args[cur_arg + 1];
3667 userlen = strlen(mysqluser);
3668 packetlen = userlen + 7;
3669 reqlen = packetlen + 9;
3670
3671 free(curproxy->check_req);
3672 curproxy->check_req = (char *)calloc(1, reqlen);
3673 curproxy->check_len = reqlen;
3674
3675 snprintf(curproxy->check_req, 4, "%c%c%c",
3676 ((unsigned char) packetlen & 0xff),
3677 ((unsigned char) (packetlen >> 8) & 0xff),
3678 ((unsigned char) (packetlen >> 16) & 0xff));
3679
3680 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003681 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003682 curproxy->check_req[8] = 1;
3683 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3684 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3685 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3686 cur_arg += 2;
3687 } else {
3688 /* unknown suboption - catchall */
3689 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3690 file, linenum, args[0], args[1]);
3691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
3693 }
3694 } /* end while loop */
3695 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003696 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003697 else if (!strcmp(args[1], "ldap-check")) {
3698 /* use LDAP request to check servers' health */
3699 free(curproxy->check_req);
3700 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003701 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003702 curproxy->options2 |= PR_O2_LDAP_CHK;
3703
3704 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3705 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3706 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3707 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003708 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003709 int cur_arg;
3710
3711 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3712 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003713 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003714
Willy Tarreau87cf5142011-08-19 22:57:24 +02003715 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003716
3717 free(curproxy->fwdfor_hdr_name);
3718 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3719 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3720
3721 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3722 cur_arg = 2;
3723 while (*(args[cur_arg])) {
3724 if (!strcmp(args[cur_arg], "except")) {
3725 /* suboption except - needs additional argument for it */
3726 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3727 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3728 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003731 }
3732 /* flush useless bits */
3733 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003734 cur_arg += 2;
3735 } else if (!strcmp(args[cur_arg], "header")) {
3736 /* suboption header - needs additional argument for it */
3737 if (*(args[cur_arg+1]) == 0) {
3738 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3739 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003742 }
3743 free(curproxy->fwdfor_hdr_name);
3744 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3745 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3746 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003747 } else if (!strcmp(args[cur_arg], "if-none")) {
3748 curproxy->options &= ~PR_O_FF_ALWAYS;
3749 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003750 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003751 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003752 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003753 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003756 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003757 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003758 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003759 else if (!strcmp(args[1], "originalto")) {
3760 int cur_arg;
3761
3762 /* insert x-original-to field, but not for the IP address listed as an except.
3763 * set default options (ie: bitfield, header name, etc)
3764 */
3765
3766 curproxy->options |= PR_O_ORGTO;
3767
3768 free(curproxy->orgto_hdr_name);
3769 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3770 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3771
Willy Tarreau87cf5142011-08-19 22:57:24 +02003772 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003773 cur_arg = 2;
3774 while (*(args[cur_arg])) {
3775 if (!strcmp(args[cur_arg], "except")) {
3776 /* suboption except - needs additional argument for it */
3777 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3778 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3779 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003782 }
3783 /* flush useless bits */
3784 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3785 cur_arg += 2;
3786 } else if (!strcmp(args[cur_arg], "header")) {
3787 /* suboption header - needs additional argument for it */
3788 if (*(args[cur_arg+1]) == 0) {
3789 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3790 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003793 }
3794 free(curproxy->orgto_hdr_name);
3795 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3796 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3797 cur_arg += 2;
3798 } else {
3799 /* unknown suboption - catchall */
3800 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3801 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003804 }
3805 } /* end while loop */
3806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 else {
3808 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 }
Willy Tarreau93893792009-07-23 13:19:11 +02003812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003814 else if (!strcmp(args[0], "default_backend")) {
3815 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003817
3818 if (*(args[1]) == 0) {
3819 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003822 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003823 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003824 curproxy->defbe.name = strdup(args[1]);
3825 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003829
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003830 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3831 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 /* enable reconnections to dispatch */
3834 curproxy->options |= PR_O_REDISP;
3835 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003836 else if (!strcmp(args[0], "http-check")) {
3837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003839
3840 if (strcmp(args[1], "disable-on-404") == 0) {
3841 /* enable a graceful server shutdown on an HTTP 404 response */
3842 curproxy->options |= PR_O_DISABLE404;
3843 }
Willy Tarreauef781042010-01-27 11:53:01 +01003844 else if (strcmp(args[1], "send-state") == 0) {
3845 /* enable emission of the apparent state of a server in HTTP checks */
3846 curproxy->options2 |= PR_O2_CHK_SNDST;
3847 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003848 else if (strcmp(args[1], "expect") == 0) {
3849 const char *ptr_arg;
3850 int cur_arg;
3851
3852 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3853 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
3856 }
3857
3858 cur_arg = 2;
3859 /* consider exclamation marks, sole or at the beginning of a word */
3860 while (*(ptr_arg = args[cur_arg])) {
3861 while (*ptr_arg == '!') {
3862 curproxy->options2 ^= PR_O2_EXP_INV;
3863 ptr_arg++;
3864 }
3865 if (*ptr_arg)
3866 break;
3867 cur_arg++;
3868 }
3869 /* now ptr_arg points to the beginning of a word past any possible
3870 * exclamation mark, and cur_arg is the argument which holds this word.
3871 */
3872 if (strcmp(ptr_arg, "status") == 0) {
3873 if (!*(args[cur_arg + 1])) {
3874 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3875 file, linenum, args[0], args[1], ptr_arg);
3876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
3878 }
3879 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003880 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003881 curproxy->expect_str = strdup(args[cur_arg + 1]);
3882 }
3883 else if (strcmp(ptr_arg, "string") == 0) {
3884 if (!*(args[cur_arg + 1])) {
3885 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3886 file, linenum, args[0], args[1], ptr_arg);
3887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
3889 }
3890 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003891 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003892 curproxy->expect_str = strdup(args[cur_arg + 1]);
3893 }
3894 else if (strcmp(ptr_arg, "rstatus") == 0) {
3895 if (!*(args[cur_arg + 1])) {
3896 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3897 file, linenum, args[0], args[1], ptr_arg);
3898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
3900 }
3901 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003902 free(curproxy->expect_str);
3903 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3904 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003905 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3906 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3907 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3908 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
3911 }
3912 }
3913 else if (strcmp(ptr_arg, "rstring") == 0) {
3914 if (!*(args[cur_arg + 1])) {
3915 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3916 file, linenum, args[0], args[1], ptr_arg);
3917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
3919 }
3920 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003921 free(curproxy->expect_str);
3922 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3923 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003924 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3925 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3926 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3927 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
3930 }
3931 }
3932 else {
3933 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3934 file, linenum, args[0], args[1], ptr_arg);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003939 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003940 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 +02003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003943 }
3944 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003945 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003946 if (curproxy == &defproxy) {
3947 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003950 }
3951
Willy Tarreaub80c2302007-11-30 20:51:32 +01003952 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003954
3955 if (strcmp(args[1], "fail") == 0) {
3956 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003957 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003958 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3959 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003960 err_code |= ERR_ALERT | ERR_FATAL;
3961 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003962 }
3963
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003964 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3965 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3966 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003969 }
3970 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3971 }
3972 else {
3973 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003976 }
3977 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978#ifdef TPROXY
3979 else if (!strcmp(args[0], "transparent")) {
3980 /* enable transparent proxy connections */
3981 curproxy->options |= PR_O_TRANSP;
3982 }
3983#endif
3984 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003985 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003986 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003987
Willy Tarreaubaaee002006-06-26 02:48:02 +02003988 if (*(args[1]) == 0) {
3989 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 }
3993 curproxy->maxconn = atol(args[1]);
3994 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003995 else if (!strcmp(args[0], "backlog")) { /* backlog */
3996 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003998
3999 if (*(args[1]) == 0) {
4000 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004003 }
4004 curproxy->backlog = atol(args[1]);
4005 }
Willy Tarreau86034312006-12-29 00:10:33 +01004006 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004007 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004009
Willy Tarreau86034312006-12-29 00:10:33 +01004010 if (*(args[1]) == 0) {
4011 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004014 }
4015 curproxy->fullconn = atol(args[1]);
4016 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004017 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4018 if (*(args[1]) == 0) {
4019 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004023 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4024 if (err) {
4025 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4026 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004029 }
4030 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 }
4032 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004033 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004034 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004035 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004036
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 if (curproxy == &defproxy) {
4038 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004042 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004044
Willy Tarreau902636f2013-03-10 19:44:48 +01004045 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004046 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004047 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004048 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004049 goto out;
4050 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004051
4052 proto = protocol_by_family(sk->ss_family);
4053 if (!proto || !proto->connect) {
4054 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4055 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004056 err_code |= ERR_ALERT | ERR_FATAL;
4057 goto out;
4058 }
4059
4060 if (port1 != port2) {
4061 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4062 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004066
4067 if (!port1) {
4068 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4069 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004070 err_code |= ERR_ALERT | ERR_FATAL;
4071 goto out;
4072 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004073
Willy Tarreaud5191e72010-02-09 20:50:45 +01004074 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004075 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004076 }
4077 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004078 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004079 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004080
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004081 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4082 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004087 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4089 err_code |= ERR_WARN;
4090
4091 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4092 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4093 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4094 }
4095 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4096 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4097 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4098 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004099 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4100 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4101 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4102 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004103 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004104 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
4107 }
4108 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004109 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004110 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004111 short realport = 0;
4112 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004114 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004118 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004119 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004120 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121
4122 if (!*args[2]) {
4123 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4124 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004128
4129 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004130 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004131 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4132 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004135 }
4136
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004137 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004138 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004139 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004140 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004141
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004142 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4143 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4144 err_code |= ERR_ALERT | ERR_ABORT;
4145 goto out;
4146 }
4147
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004148 /* the servers are linked backwards first */
4149 newsrv->next = curproxy->srv;
4150 curproxy->srv = newsrv;
4151 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004152 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004155 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004156 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004157 LIST_INIT(&newsrv->pendconns);
4158 do_check = 0;
4159 newsrv->state = SRV_RUNNING; /* early server setup */
4160 newsrv->last_change = now.tv_sec;
4161 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004163 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004164 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004165 * - IP: => port=+0, relative
4166 * - IP:N => port=N, absolute
4167 * - IP:+N => port=+N, relative
4168 * - IP:-N => port=-N, relative
4169 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004170 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004171 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004172 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004173 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004174 goto out;
4175 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004176
4177 proto = protocol_by_family(sk->ss_family);
4178 if (!proto || !proto->connect) {
4179 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4180 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
4183 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004184
4185 if (!port1 || !port2) {
4186 /* no port specified, +offset, -offset */
4187 newsrv->state |= SRV_MAPPORTS;
4188 }
4189 else if (port1 != port2) {
4190 /* port range */
4191 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4192 file, linenum, args[0], args[1], args[2]);
4193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
4196 else {
4197 /* used by checks */
4198 realport = port1;
4199 }
4200
Willy Tarreaud5191e72010-02-09 20:50:45 +01004201 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004202 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4203 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004204
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004205 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004206 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4207 file, linenum, newsrv->addr.ss_family, args[2]);
4208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
4210 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004211
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004212 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004213 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004214 newsrv->inter = curproxy->defsrv.inter;
4215 newsrv->fastinter = curproxy->defsrv.fastinter;
4216 newsrv->downinter = curproxy->defsrv.downinter;
4217 newsrv->rise = curproxy->defsrv.rise;
4218 newsrv->fall = curproxy->defsrv.fall;
4219 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4220 newsrv->minconn = curproxy->defsrv.minconn;
4221 newsrv->maxconn = curproxy->defsrv.maxconn;
4222 newsrv->slowstart = curproxy->defsrv.slowstart;
4223 newsrv->onerror = curproxy->defsrv.onerror;
4224 newsrv->consecutive_errors_limit
4225 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004226#ifdef OPENSSL
4227 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4228#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004229 newsrv->uweight = newsrv->iweight
4230 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004232 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004234 cur_arg = 3;
4235 } else {
4236 newsrv = &curproxy->defsrv;
4237 cur_arg = 1;
4238 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004239
Willy Tarreaubaaee002006-06-26 02:48:02 +02004240 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004241 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 newsrv->cookie = strdup(args[cur_arg + 1]);
4243 newsrv->cklen = strlen(args[cur_arg + 1]);
4244 cur_arg += 2;
4245 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004246 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004247 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4248 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4249 cur_arg += 2;
4250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004252 if (!*args[cur_arg + 1]) {
4253 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4254 file, linenum, args[cur_arg]);
4255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
4257 }
4258
Willy Tarreaubaaee002006-06-26 02:48:02 +02004259 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004260 if (newsrv->rise <= 0) {
4261 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4262 file, linenum, args[cur_arg]);
4263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265 }
4266
Willy Tarreau96839092010-03-29 10:02:24 +02004267 if (newsrv->health)
4268 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004269 cur_arg += 2;
4270 }
4271 else if (!strcmp(args[cur_arg], "fall")) {
4272 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004273
4274 if (!*args[cur_arg + 1]) {
4275 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4276 file, linenum, args[cur_arg]);
4277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
4279 }
4280
4281 if (newsrv->fall <= 0) {
4282 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4283 file, linenum, args[cur_arg]);
4284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
4286 }
4287
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 cur_arg += 2;
4289 }
4290 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004291 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4292 if (err) {
4293 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4294 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004297 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004298 if (val <= 0) {
4299 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4300 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004303 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004304 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004305 cur_arg += 2;
4306 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004307 else if (!strcmp(args[cur_arg], "fastinter")) {
4308 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4309 if (err) {
4310 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4311 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004314 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004315 if (val <= 0) {
4316 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4317 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004320 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004321 newsrv->fastinter = val;
4322 cur_arg += 2;
4323 }
4324 else if (!strcmp(args[cur_arg], "downinter")) {
4325 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4326 if (err) {
4327 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4328 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004331 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004332 if (val <= 0) {
4333 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4334 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004337 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004338 newsrv->downinter = val;
4339 cur_arg += 2;
4340 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004341 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004342 struct sockaddr_storage *sk;
4343 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004344 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004345
Willy Tarreau902636f2013-03-10 19:44:48 +01004346 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004347 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004348 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004349 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004350 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004351 goto out;
4352 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004353
4354 proto = protocol_by_family(sk->ss_family);
4355 if (!proto || !proto->connect) {
4356 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004357 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
4360 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004361
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004362 if (port1 != port2) {
4363 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4364 file, linenum, args[cur_arg], args[cur_arg + 1]);
4365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
4367 }
4368
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004369 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004370 cur_arg += 2;
4371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004373 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004374 cur_arg += 2;
4375 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004376 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 newsrv->state |= SRV_BACKUP;
4378 cur_arg ++;
4379 }
Simon Hormanfa461682011-06-25 09:39:49 +09004380 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4381 newsrv->state |= SRV_NON_STICK;
4382 cur_arg ++;
4383 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004384 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4385 newsrv->state |= SRV_SEND_PROXY;
4386 cur_arg ++;
4387 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004388 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4389 newsrv->check.send_proxy = 1;
4390 cur_arg ++;
4391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004392 else if (!strcmp(args[cur_arg], "weight")) {
4393 int w;
4394 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004395 if (w < 0 || w > 256) {
4396 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004400 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004401 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 cur_arg += 2;
4403 }
4404 else if (!strcmp(args[cur_arg], "minconn")) {
4405 newsrv->minconn = atol(args[cur_arg + 1]);
4406 cur_arg += 2;
4407 }
4408 else if (!strcmp(args[cur_arg], "maxconn")) {
4409 newsrv->maxconn = atol(args[cur_arg + 1]);
4410 cur_arg += 2;
4411 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004412 else if (!strcmp(args[cur_arg], "maxqueue")) {
4413 newsrv->maxqueue = atol(args[cur_arg + 1]);
4414 cur_arg += 2;
4415 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004416 else if (!strcmp(args[cur_arg], "slowstart")) {
4417 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004418 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004419 if (err) {
4420 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4421 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004424 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004425 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004426 cur_arg += 2;
4427 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004428 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004429
4430 if (!*args[cur_arg + 1]) {
4431 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4432 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004435 }
4436
4437 newsrv->trackit = strdup(args[cur_arg + 1]);
4438
4439 cur_arg += 2;
4440 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004441 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 global.maxsock++;
4443 do_check = 1;
4444 cur_arg += 1;
4445 }
Willy Tarreau96839092010-03-29 10:02:24 +02004446 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4447 newsrv->state |= SRV_MAINTAIN;
4448 newsrv->state &= ~SRV_RUNNING;
4449 newsrv->health = 0;
4450 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004451 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004452 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004453 if (!strcmp(args[cur_arg + 1], "none"))
4454 newsrv->observe = HANA_OBS_NONE;
4455 else if (!strcmp(args[cur_arg + 1], "layer4"))
4456 newsrv->observe = HANA_OBS_LAYER4;
4457 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4458 if (curproxy->mode != PR_MODE_HTTP) {
4459 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4460 file, linenum, args[cur_arg + 1]);
4461 err_code |= ERR_ALERT;
4462 }
4463 newsrv->observe = HANA_OBS_LAYER7;
4464 }
4465 else {
4466 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004467 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004468 file, linenum, args[cur_arg], args[cur_arg + 1]);
4469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
4471 }
4472
4473 cur_arg += 2;
4474 }
4475 else if (!strcmp(args[cur_arg], "on-error")) {
4476 if (!strcmp(args[cur_arg + 1], "fastinter"))
4477 newsrv->onerror = HANA_ONERR_FASTINTER;
4478 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4479 newsrv->onerror = HANA_ONERR_FAILCHK;
4480 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4481 newsrv->onerror = HANA_ONERR_SUDDTH;
4482 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4483 newsrv->onerror = HANA_ONERR_MARKDWN;
4484 else {
4485 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004486 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004487 file, linenum, args[cur_arg], args[cur_arg + 1]);
4488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
4490 }
4491
4492 cur_arg += 2;
4493 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004494 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4495 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4496 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4497 else {
4498 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4499 file, linenum, args[cur_arg], args[cur_arg + 1]);
4500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
4502 }
4503
4504 cur_arg += 2;
4505 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004506 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4507 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4508 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4509 else {
4510 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4511 file, linenum, args[cur_arg], args[cur_arg + 1]);
4512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
4514 }
4515
4516 cur_arg += 2;
4517 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004518 else if (!strcmp(args[cur_arg], "error-limit")) {
4519 if (!*args[cur_arg + 1]) {
4520 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4521 file, linenum, args[cur_arg]);
4522 err_code |= ERR_ALERT | ERR_FATAL;
4523 goto out;
4524 }
4525
4526 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4527
4528 if (newsrv->consecutive_errors_limit <= 0) {
4529 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4530 file, linenum, args[cur_arg]);
4531 err_code |= ERR_ALERT | ERR_FATAL;
4532 goto out;
4533 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004534 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004535 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004536 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004537 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004538 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004539 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004540
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004542 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4543 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004544 err_code |= ERR_ALERT | ERR_FATAL;
4545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004546 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004547
Willy Tarreauef9a3602012-12-08 22:29:20 +01004548 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004549 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004550 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004551 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004552 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004553 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004554 goto out;
4555 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004556
4557 proto = protocol_by_family(sk->ss_family);
4558 if (!proto || !proto->connect) {
4559 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4560 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004561 err_code |= ERR_ALERT | ERR_FATAL;
4562 goto out;
4563 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004564
Willy Tarreauef9a3602012-12-08 22:29:20 +01004565 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004566
4567 if (port_low != port_high) {
4568 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004569
4570 if (!port_low || !port_high) {
4571 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4572 file, linenum, args[cur_arg], args[cur_arg + 1]);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
4576
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004577 if (port_low <= 0 || port_low > 65535 ||
4578 port_high <= 0 || port_high > 65535 ||
4579 port_low > port_high) {
4580 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4581 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004584 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004585 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4586 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4587 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004588 }
4589
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004591 while (*(args[cur_arg])) {
4592 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004593#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4594#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004595 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004596 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4597 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004600 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004601#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004602 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004603 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004604 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004605 err_code |= ERR_ALERT | ERR_FATAL;
4606 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004607 }
4608 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004609 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4610 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004611 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004612 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4613 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004614 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4615 char *name, *end;
4616
4617 name = args[cur_arg+1] + 7;
4618 while (isspace(*name))
4619 name++;
4620
4621 end = name;
4622 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4623 end++;
4624
Willy Tarreauef9a3602012-12-08 22:29:20 +01004625 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4626 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4627 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4628 newsrv->conn_src.bind_hdr_len = end - name;
4629 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4630 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4631 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004632
4633 /* now look for an occurrence number */
4634 while (isspace(*end))
4635 end++;
4636 if (*end == ',') {
4637 end++;
4638 name = end;
4639 if (*end == '-')
4640 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004641 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004642 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004643 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004644 }
4645
Willy Tarreauef9a3602012-12-08 22:29:20 +01004646 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004647 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4648 " occurrences values smaller than %d.\n",
4649 file, linenum, MAX_HDR_HISTORY);
4650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
4652 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004653 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004654 struct sockaddr_storage *sk;
4655 int port1, port2;
4656
Willy Tarreau902636f2013-03-10 19:44:48 +01004657 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004658 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004659 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004660 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004661 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004662 goto out;
4663 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004664
4665 proto = protocol_by_family(sk->ss_family);
4666 if (!proto || !proto->connect) {
4667 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4668 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
4671 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004672
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004673 if (port1 != port2) {
4674 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4675 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004676 err_code |= ERR_ALERT | ERR_FATAL;
4677 goto out;
4678 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004679 newsrv->conn_src.tproxy_addr = *sk;
4680 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004681 }
4682 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004683#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004684 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004685#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004686 cur_arg += 2;
4687 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004688#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004689 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004690 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004691 err_code |= ERR_ALERT | ERR_FATAL;
4692 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004693#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004694 } /* "usesrc" */
4695
4696 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4697#ifdef SO_BINDTODEVICE
4698 if (!*args[cur_arg + 1]) {
4699 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4700 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004701 err_code |= ERR_ALERT | ERR_FATAL;
4702 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004703 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004704 free(newsrv->conn_src.iface_name);
4705 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4706 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004707 global.last_checks |= LSTCHK_NETADM;
4708#else
4709 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4710 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004711 err_code |= ERR_ALERT | ERR_FATAL;
4712 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004713#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004714 cur_arg += 2;
4715 continue;
4716 }
4717 /* this keyword in not an option of "source" */
4718 break;
4719 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004720 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004721 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004722 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4723 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004726 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004728 static int srv_dumped;
4729 struct srv_kw *kw;
4730 char *err;
4731
4732 kw = srv_find_kw(args[cur_arg]);
4733 if (kw) {
4734 char *err = NULL;
4735 int code;
4736
4737 if (!kw->parse) {
4738 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4739 file, linenum, args[0], args[1], args[cur_arg]);
4740 cur_arg += 1 + kw->skip ;
4741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
4743 }
4744
4745 if (defsrv && !kw->default_ok) {
4746 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4747 file, linenum, args[0], args[1], args[cur_arg]);
4748 cur_arg += 1 + kw->skip ;
4749 err_code |= ERR_ALERT;
4750 continue;
4751 }
4752
4753 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4754 err_code |= code;
4755
4756 if (code) {
4757 if (err && *err) {
4758 indent_msg(&err, 2);
4759 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4760 }
4761 else
4762 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4763 file, linenum, args[0], args[1], args[cur_arg]);
4764 if (code & ERR_FATAL) {
4765 free(err);
4766 cur_arg += 1 + kw->skip;
4767 goto out;
4768 }
4769 }
4770 free(err);
4771 cur_arg += 1 + kw->skip;
4772 continue;
4773 }
4774
4775 err = NULL;
4776 if (!srv_dumped) {
4777 srv_dump_kws(&err);
4778 indent_msg(&err, 4);
4779 srv_dumped = 1;
4780 }
4781
4782 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4783 file, linenum, args[0], args[1], args[cur_arg],
4784 err ? " Registered keywords :" : "", err ? err : "");
4785 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004786
Willy Tarreau93893792009-07-23 13:19:11 +02004787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004789 }
4790 }
4791
4792 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004793 if (newsrv->trackit) {
4794 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4795 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004796 err_code |= ERR_ALERT | ERR_FATAL;
4797 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004798 }
4799
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004800 /* If neither a port nor an addr was specified and no check transport
4801 * layer is forced, then the transport layer used by the checks is the
4802 * same as for the production traffic. Otherwise we use raw_sock by
4803 * default, unless one is specified.
4804 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004805 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004806#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004807 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004808#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004809 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4810 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004811 /* try to get the port from check.addr if check.port not set */
4812 if (!newsrv->check.port)
4813 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004814
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004815 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004816 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004817
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004818 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004819 /* not yet valid, because no port was set on
4820 * the server either. We'll check if we have
4821 * a known port on the first listener.
4822 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004823 struct listener *l;
4824
4825 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004826 newsrv->check.port = get_host_port(&l->addr);
4827 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004828 break;
4829 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004830 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004831 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4833 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004837
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004838 /* Allocate buffer for check requests... */
4839 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004840 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4841 err_code |= ERR_ALERT | ERR_ABORT;
4842 goto out;
4843 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004844 newsrv->check.bi->size = global.tune.chksize;
4845
4846 /* Allocate buffer for check responses... */
4847 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4848 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4849 err_code |= ERR_ALERT | ERR_ABORT;
4850 goto out;
4851 }
4852 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004853
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004854 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004855 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004856 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4857 err_code |= ERR_ALERT | ERR_ABORT;
4858 goto out;
4859 }
4860
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004861 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4862 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 newsrv->state |= SRV_CHECKED;
4864 }
4865
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004866 if (!defsrv) {
4867 if (newsrv->state & SRV_BACKUP)
4868 curproxy->srv_bck++;
4869 else
4870 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004871
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004872 newsrv->prev_state = newsrv->state;
4873 }
William Lallemanda73203e2012-03-12 12:48:57 +01004874 }
4875
4876 else if (strcmp(args[0], "unique-id-format") == 0) {
4877 if (!*(args[1])) {
4878 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4879 err_code |= ERR_ALERT | ERR_FATAL;
4880 goto out;
4881 }
William Lallemand3203ff42012-11-11 17:30:56 +01004882 if (*(args[2])) {
4883 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
4886 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004887 free(curproxy->conf.uniqueid_format_string);
4888 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004889
Willy Tarreau62a61232013-04-12 18:13:46 +02004890 free(curproxy->conf.uif_file);
4891 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4892 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004893 }
William Lallemanda73203e2012-03-12 12:48:57 +01004894
4895 else if (strcmp(args[0], "unique-id-header") == 0) {
4896 if (!*(args[1])) {
4897 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
4900 }
4901 free(curproxy->header_unique_id);
4902 curproxy->header_unique_id = strdup(args[1]);
4903 }
4904
William Lallemand723b73a2012-02-08 16:37:49 +01004905 else if (strcmp(args[0], "log-format") == 0) {
4906 if (!*(args[1])) {
4907 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
4910 }
William Lallemand3203ff42012-11-11 17:30:56 +01004911 if (*(args[2])) {
4912 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
4915 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004916
Willy Tarreau62a61232013-04-12 18:13:46 +02004917 if (curproxy->conf.logformat_string != default_http_log_format &&
4918 curproxy->conf.logformat_string != default_tcp_log_format &&
4919 curproxy->conf.logformat_string != clf_http_log_format)
4920 free(curproxy->conf.logformat_string);
4921 curproxy->conf.logformat_string = strdup(args[1]);
4922
4923 free(curproxy->conf.lfs_file);
4924 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4925 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004926
4927 /* get a chance to improve log-format error reporting by
4928 * reporting the correct line-number when possible.
4929 */
4930 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4931 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4932 file, linenum, curproxy->id);
4933 err_code |= ERR_WARN;
4934 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004935 }
William Lallemand723b73a2012-02-08 16:37:49 +01004936
William Lallemand0f99e342011-10-12 17:50:54 +02004937 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4938 /* delete previous herited or defined syslog servers */
4939 struct logsrv *back;
4940
4941 if (*(args[1]) != 0) {
4942 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
4945 }
4946
William Lallemand723b73a2012-02-08 16:37:49 +01004947 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4948 LIST_DEL(&tmplogsrv->list);
4949 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004950 }
4951 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004953 struct logsrv *logsrv;
4954
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004956 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004957 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004958 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004959 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004960 LIST_INIT(&node->list);
4961 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 }
4964 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004965 struct sockaddr_storage *sk;
4966 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004967
4968 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969
William Lallemand0f99e342011-10-12 17:50:54 +02004970 logsrv->facility = get_log_facility(args[2]);
4971 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
4975
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 }
4977
William Lallemand0f99e342011-10-12 17:50:54 +02004978 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004980 logsrv->level = get_log_level(args[3]);
4981 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004983 err_code |= ERR_ALERT | ERR_FATAL;
4984 goto out;
4985
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 }
4987 }
4988
William Lallemand0f99e342011-10-12 17:50:54 +02004989 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004990 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004991 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004992 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004993 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
4996
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004997 }
4998 }
4999
Willy Tarreau902636f2013-03-10 19:44:48 +01005000 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005001 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005002 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005003 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005004 goto out;
5005 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005006
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005007 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005008
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005009 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005010 if (port1 != port2) {
5011 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5012 file, linenum, args[0], args[1]);
5013 err_code |= ERR_ALERT | ERR_FATAL;
5014 goto out;
5015 }
5016
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005017 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005018 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
William Lallemand0f99e342011-10-12 17:50:54 +02005020
5021 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022 }
5023 else {
5024 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5025 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 }
5029 }
5030 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005031 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005032 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005033 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005034 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005035
Willy Tarreau977b8e42006-12-29 14:19:17 +01005036 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005037 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005038
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005040 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5041 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005045
5046 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005047 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5048 free(curproxy->conn_src.iface_name);
5049 curproxy->conn_src.iface_name = NULL;
5050 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005051
Willy Tarreau902636f2013-03-10 19:44:48 +01005052 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005053 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005054 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005055 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005056 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005057 goto out;
5058 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005059
5060 proto = protocol_by_family(sk->ss_family);
5061 if (!proto || !proto->connect) {
5062 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005063 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
5066 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005067
5068 if (port1 != port2) {
5069 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5070 file, linenum, args[0], args[1]);
5071 err_code |= ERR_ALERT | ERR_FATAL;
5072 goto out;
5073 }
5074
Willy Tarreauef9a3602012-12-08 22:29:20 +01005075 curproxy->conn_src.source_addr = *sk;
5076 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005077
5078 cur_arg = 2;
5079 while (*(args[cur_arg])) {
5080 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005081#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5082#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005083 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005084 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5085 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005088 }
5089#endif
5090 if (!*args[cur_arg + 1]) {
5091 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5092 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005095 }
5096
5097 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005098 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5099 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005100 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005101 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5102 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005103 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5104 char *name, *end;
5105
5106 name = args[cur_arg+1] + 7;
5107 while (isspace(*name))
5108 name++;
5109
5110 end = name;
5111 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5112 end++;
5113
Willy Tarreauef9a3602012-12-08 22:29:20 +01005114 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5115 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5116 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5117 curproxy->conn_src.bind_hdr_len = end - name;
5118 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5119 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5120 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005121
5122 /* now look for an occurrence number */
5123 while (isspace(*end))
5124 end++;
5125 if (*end == ',') {
5126 end++;
5127 name = end;
5128 if (*end == '-')
5129 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005130 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005131 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005132 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005133 }
5134
Willy Tarreauef9a3602012-12-08 22:29:20 +01005135 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005136 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5137 " occurrences values smaller than %d.\n",
5138 file, linenum, MAX_HDR_HISTORY);
5139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
5141 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005142 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005143 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005144
Willy Tarreau902636f2013-03-10 19:44:48 +01005145 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005146 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005147 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005148 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005149 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005150 goto out;
5151 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005152
5153 proto = protocol_by_family(sk->ss_family);
5154 if (!proto || !proto->connect) {
5155 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5156 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
5159 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005160
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005161 if (port1 != port2) {
5162 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5163 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
5166 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005167 curproxy->conn_src.tproxy_addr = *sk;
5168 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005169 }
5170 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005171#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005172 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005173#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005174#else /* no TPROXY support */
5175 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005176 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005179#endif
5180 cur_arg += 2;
5181 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005182 }
5183
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005184 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5185#ifdef SO_BINDTODEVICE
5186 if (!*args[cur_arg + 1]) {
5187 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5188 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005191 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005192 free(curproxy->conn_src.iface_name);
5193 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5194 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005195 global.last_checks |= LSTCHK_NETADM;
5196#else
5197 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5198 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005199 err_code |= ERR_ALERT | ERR_FATAL;
5200 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005201#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005202 cur_arg += 2;
5203 continue;
5204 }
5205 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005206 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005211 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5212 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5213 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005218 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005219 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5220 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005224
5225 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005226 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005227 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 }
5231 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005232 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005233 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005234 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005235 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 }
5238 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005240 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005241 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 }
5245 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005247 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005248 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005251 }
5252 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005254 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005255 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005259 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005260 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005261 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005262 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005264 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005265 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005266 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005268 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005269 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005271 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005272 }
5273 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005275 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005276 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005278 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005281 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5283 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005284 err_code |= ERR_ALERT | ERR_FATAL;
5285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005287
5288 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005289 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005290 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 }
5294 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005295 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005296 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005297 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005298 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 }
5301 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005302 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005303 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005304 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005305 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307 }
5308 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005309 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005310 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005311 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005312 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 }
5315 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005316 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005317 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005318 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005319 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005322 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005323 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005324 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005325 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005326 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005327 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005330 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005331
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 if (curproxy == &defproxy) {
5333 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005336 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005337 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005338 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005339
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 if (*(args[1]) == 0) {
5341 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005345
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005346 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005347 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5348 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5349 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005350 err_code |= ERR_ALERT | ERR_FATAL;
5351 goto out;
5352 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005353 err_code |= warnif_cond_conflicts(cond,
5354 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5355 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005356 }
5357 else if (*args[2]) {
5358 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5359 file, linenum, args[0], args[2]);
5360 err_code |= ERR_ALERT | ERR_FATAL;
5361 goto out;
5362 }
5363
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005364 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005365 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005366 wl->s = strdup(args[1]);
5367 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005368 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 }
5370 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005371 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5373 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005377
Willy Tarreauade5ec42010-01-28 19:33:49 +01005378 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005379 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005380 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005381 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 }
5384 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005385 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005386 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005387 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005388 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 }
5391 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005392 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005393 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005394 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005395 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397 }
5398 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005399 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5401 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005402 err_code |= ERR_ALERT | ERR_FATAL;
5403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005404 }
5405
Willy Tarreauade5ec42010-01-28 19:33:49 +01005406 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005407 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005408 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005409 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005411 }
5412 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005413 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005414 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005415 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005416 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005418 }
5419 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005420 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005421 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005422 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005423 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005425 }
5426 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005427 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005428
Willy Tarreaubaaee002006-06-26 02:48:02 +02005429 if (curproxy == &defproxy) {
5430 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005434 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005435 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005436
Willy Tarreaubaaee002006-06-26 02:48:02 +02005437 if (*(args[1]) == 0) {
5438 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005441 }
5442
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005443 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005444 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5445 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5446 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005447 err_code |= ERR_ALERT | ERR_FATAL;
5448 goto out;
5449 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005450 err_code |= warnif_cond_conflicts(cond,
5451 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5452 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005453 }
5454 else if (*args[2]) {
5455 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5456 file, linenum, args[0], args[2]);
5457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
5459 }
5460
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005461 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005462 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005463 wl->s = strdup(args[1]);
5464 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005465 }
5466 else if (!strcmp(args[0], "errorloc") ||
5467 !strcmp(args[0], "errorloc302") ||
5468 !strcmp(args[0], "errorloc303")) { /* error location */
5469 int errnum, errlen;
5470 char *err;
5471
Willy Tarreau977b8e42006-12-29 14:19:17 +01005472 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005473 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005474
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005476 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 }
5480
5481 errnum = atol(args[1]);
5482 if (!strcmp(args[0], "errorloc303")) {
5483 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5484 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5485 } else {
5486 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5487 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5488 }
5489
Willy Tarreau0f772532006-12-23 20:51:41 +01005490 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5491 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005492 chunk_destroy(&curproxy->errmsg[rc]);
5493 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005494 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005497
5498 if (rc >= HTTP_ERR_SIZE) {
5499 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5500 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005501 free(err);
5502 }
5503 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005504 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5505 int errnum, errlen, fd;
5506 char *err;
5507 struct stat stat;
5508
5509 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005510 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005511
5512 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005513 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005516 }
5517
5518 fd = open(args[2], O_RDONLY);
5519 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5520 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5521 file, linenum, args[2], args[1]);
5522 if (fd >= 0)
5523 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005526 }
5527
Willy Tarreau27a674e2009-08-17 07:23:33 +02005528 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005529 errlen = stat.st_size;
5530 } else {
5531 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005532 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005533 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005534 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005535 }
5536
5537 err = malloc(errlen); /* malloc() must succeed during parsing */
5538 errnum = read(fd, err, errlen);
5539 if (errnum != errlen) {
5540 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5541 file, linenum, args[2], args[1]);
5542 close(fd);
5543 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005544 err_code |= ERR_ALERT | ERR_FATAL;
5545 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005546 }
5547 close(fd);
5548
5549 errnum = atol(args[1]);
5550 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5551 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005552 chunk_destroy(&curproxy->errmsg[rc]);
5553 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005554 break;
5555 }
5556 }
5557
5558 if (rc >= HTTP_ERR_SIZE) {
5559 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5560 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005561 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005562 free(err);
5563 }
5564 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005565 else if (!strcmp(args[0], "compression")) {
5566 struct comp *comp;
5567 if (curproxy->comp == NULL) {
5568 comp = calloc(1, sizeof(struct comp));
5569 curproxy->comp = comp;
5570 } else {
5571 comp = curproxy->comp;
5572 }
5573
5574 if (!strcmp(args[1], "algo")) {
5575 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005576 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005577
William Lallemand82fe75c2012-10-23 10:25:10 +02005578 cur_arg = 2;
5579 if (!*args[cur_arg]) {
5580 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5581 file, linenum, args[0]);
5582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
5584 }
5585 while (*(args[cur_arg])) {
5586 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5587 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5588 file, linenum, args[0], args[cur_arg]);
5589 err_code |= ERR_ALERT | ERR_FATAL;
5590 goto out;
5591 }
William Lallemand552df672012-11-07 13:21:47 +01005592 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5593 curproxy->comp->algos->end(&ctx);
5594 } else {
5595 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5596 file, linenum, args[0], args[cur_arg]);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005600 cur_arg ++;
5601 continue;
5602 }
5603 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005604 else if (!strcmp(args[1], "offload")) {
5605 comp->offload = 1;
5606 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005607 else if (!strcmp(args[1], "type")) {
5608 int cur_arg;
5609 cur_arg = 2;
5610 if (!*args[cur_arg]) {
5611 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5612 file, linenum, args[0]);
5613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
5615 }
5616 while (*(args[cur_arg])) {
5617 comp_append_type(comp, args[cur_arg]);
5618 cur_arg ++;
5619 continue;
5620 }
5621 }
5622 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005623 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005624 file, linenum, args[0]);
5625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
5627 }
5628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005629 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005630 struct cfg_kw_list *kwl;
5631 int index;
5632
5633 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5634 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5635 if (kwl->kw[index].section != CFG_LISTEN)
5636 continue;
5637 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5638 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005639 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005640 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005641 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005642 err_code |= ERR_ALERT | ERR_FATAL;
5643 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005644 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005645 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005646 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005647 err_code |= ERR_WARN;
5648 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005649 }
Willy Tarreau93893792009-07-23 13:19:11 +02005650 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005651 }
5652 }
5653 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005654
Willy Tarreau6daf3432008-01-22 16:44:08 +01005655 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005656 err_code |= ERR_ALERT | ERR_FATAL;
5657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 }
Willy Tarreau93893792009-07-23 13:19:11 +02005659 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005660 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005661 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662}
5663
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005664int
5665cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5666{
5667
5668 int err_code = 0;
5669 const char *err;
5670
5671 if (!strcmp(args[0], "userlist")) { /* new userlist */
5672 struct userlist *newul;
5673
5674 if (!*args[1]) {
5675 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5676 file, linenum, args[0]);
5677 err_code |= ERR_ALERT | ERR_FATAL;
5678 goto out;
5679 }
5680
5681 err = invalid_char(args[1]);
5682 if (err) {
5683 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5684 file, linenum, *err, args[0], args[1]);
5685 err_code |= ERR_ALERT | ERR_FATAL;
5686 goto out;
5687 }
5688
5689 for (newul = userlist; newul; newul = newul->next)
5690 if (!strcmp(newul->name, args[1])) {
5691 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5692 file, linenum, args[1]);
5693 err_code |= ERR_WARN;
5694 goto out;
5695 }
5696
5697 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5698 if (!newul) {
5699 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5700 err_code |= ERR_ALERT | ERR_ABORT;
5701 goto out;
5702 }
5703
5704 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5705 newul->name = strdup(args[1]);
5706
5707 if (!newul->groupusers | !newul->name) {
5708 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5709 err_code |= ERR_ALERT | ERR_ABORT;
5710 goto out;
5711 }
5712
5713 newul->next = userlist;
5714 userlist = newul;
5715
5716 } else if (!strcmp(args[0], "group")) { /* new group */
5717 int cur_arg, i;
5718 const char *err;
5719
5720 if (!*args[1]) {
5721 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5722 file, linenum, args[0]);
5723 err_code |= ERR_ALERT | ERR_FATAL;
5724 goto out;
5725 }
5726
5727 err = invalid_char(args[1]);
5728 if (err) {
5729 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5730 file, linenum, *err, args[0], args[1]);
5731 err_code |= ERR_ALERT | ERR_FATAL;
5732 goto out;
5733 }
5734
5735 for(i = 0; i < userlist->grpcnt; i++)
5736 if (!strcmp(userlist->groups[i], args[1])) {
5737 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5738 file, linenum, args[1], userlist->name);
5739 err_code |= ERR_ALERT;
5740 goto out;
5741 }
5742
5743 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5744 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5745 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
5748 }
5749
5750 cur_arg = 2;
5751
5752 while (*args[cur_arg]) {
5753 if (!strcmp(args[cur_arg], "users")) {
5754 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5755 cur_arg += 2;
5756 continue;
5757 } else {
5758 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5759 file, linenum, args[0]);
5760 err_code |= ERR_ALERT | ERR_FATAL;
5761 goto out;
5762 }
5763 }
5764
5765 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5766 } else if (!strcmp(args[0], "user")) { /* new user */
5767 struct auth_users *newuser;
5768 int cur_arg;
5769
5770 if (!*args[1]) {
5771 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5772 file, linenum, args[0]);
5773 err_code |= ERR_ALERT | ERR_FATAL;
5774 goto out;
5775 }
5776
5777 for (newuser = userlist->users; newuser; newuser = newuser->next)
5778 if (!strcmp(newuser->user, args[1])) {
5779 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5780 file, linenum, args[1], userlist->name);
5781 err_code |= ERR_ALERT;
5782 goto out;
5783 }
5784
5785 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5786 if (!newuser) {
5787 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5788 err_code |= ERR_ALERT | ERR_ABORT;
5789 goto out;
5790 }
5791
5792 newuser->user = strdup(args[1]);
5793
5794 newuser->next = userlist->users;
5795 userlist->users = newuser;
5796
5797 cur_arg = 2;
5798
5799 while (*args[cur_arg]) {
5800 if (!strcmp(args[cur_arg], "password")) {
5801#ifndef CONFIG_HAP_CRYPT
5802 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5803 file, linenum);
5804 err_code |= ERR_ALERT;
5805#endif
5806 newuser->pass = strdup(args[cur_arg + 1]);
5807 cur_arg += 2;
5808 continue;
5809 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5810 newuser->pass = strdup(args[cur_arg + 1]);
5811 newuser->flags |= AU_O_INSECURE;
5812 cur_arg += 2;
5813 continue;
5814 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005815 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005816 cur_arg += 2;
5817 continue;
5818 } else {
5819 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5820 file, linenum, args[0]);
5821 err_code |= ERR_ALERT | ERR_FATAL;
5822 goto out;
5823 }
5824 }
5825 } else {
5826 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5827 err_code |= ERR_ALERT | ERR_FATAL;
5828 }
5829
5830out:
5831 return err_code;
5832}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833
5834/*
5835 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005836 * Returns the error code, 0 if OK, or any combination of :
5837 * - ERR_ABORT: must abort ASAP
5838 * - ERR_FATAL: we can continue parsing but not start the service
5839 * - ERR_WARN: a warning has been emitted
5840 * - ERR_ALERT: an alert has been emitted
5841 * Only the two first ones can stop processing, the two others are just
5842 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005843 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005844int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005845{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005846 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 FILE *f;
5848 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005849 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005850 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005851
Willy Tarreaubaaee002006-06-26 02:48:02 +02005852 if ((f=fopen(file,"r")) == NULL)
5853 return -1;
5854
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005855 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005856 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005857 char *end;
5858 char *args[MAX_LINE_ARGS + 1];
5859 char *line = thisline;
5860
Willy Tarreaubaaee002006-06-26 02:48:02 +02005861 linenum++;
5862
5863 end = line + strlen(line);
5864
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005865 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5866 /* Check if we reached the limit and the last char is not \n.
5867 * Watch out for the last line without the terminating '\n'!
5868 */
5869 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005870 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005871 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005872 }
5873
Willy Tarreaubaaee002006-06-26 02:48:02 +02005874 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005875 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005876 line++;
5877
5878 arg = 0;
5879 args[arg] = line;
5880
5881 while (*line && arg < MAX_LINE_ARGS) {
5882 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5883 * C equivalent value. Other combinations left unchanged (eg: \1).
5884 */
5885 if (*line == '\\') {
5886 int skip = 0;
5887 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5888 *line = line[1];
5889 skip = 1;
5890 }
5891 else if (line[1] == 'r') {
5892 *line = '\r';
5893 skip = 1;
5894 }
5895 else if (line[1] == 'n') {
5896 *line = '\n';
5897 skip = 1;
5898 }
5899 else if (line[1] == 't') {
5900 *line = '\t';
5901 skip = 1;
5902 }
5903 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005904 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 unsigned char hex1, hex2;
5906 hex1 = toupper(line[2]) - '0';
5907 hex2 = toupper(line[3]) - '0';
5908 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5909 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5910 *line = (hex1<<4) + hex2;
5911 skip = 3;
5912 }
5913 else {
5914 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005915 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 }
5917 }
5918 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005919 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005920 end -= skip;
5921 }
5922 line++;
5923 }
5924 else if (*line == '#' || *line == '\n' || *line == '\r') {
5925 /* end of string, end of loop */
5926 *line = 0;
5927 break;
5928 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005929 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005931 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005932 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005933 line++;
5934 args[++arg] = line;
5935 }
5936 else {
5937 line++;
5938 }
5939 }
5940
5941 /* empty line */
5942 if (!**args)
5943 continue;
5944
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005945 if (*line) {
5946 /* we had to stop due to too many args.
5947 * Let's terminate the string, print the offending part then cut the
5948 * last arg.
5949 */
5950 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5951 line++;
5952 *line = '\0';
5953
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005954 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005955 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005956 err_code |= ERR_ALERT | ERR_FATAL;
5957 args[arg] = line;
5958 }
5959
Willy Tarreau540abe42007-05-02 20:50:16 +02005960 /* zero out remaining args and ensure that at least one entry
5961 * is zeroed out.
5962 */
5963 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005964 args[arg] = line;
5965 }
5966
Willy Tarreau3842f002009-06-14 11:39:52 +02005967 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005968 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005969 char *tmp;
5970
Willy Tarreau3842f002009-06-14 11:39:52 +02005971 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005972 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005973 for (arg=0; *args[arg+1]; arg++)
5974 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005975 *tmp = '\0'; // fix the next arg to \0
5976 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005977 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005978 else if (!strcmp(args[0], "default")) {
5979 kwm = KWM_DEF;
5980 for (arg=0; *args[arg+1]; arg++)
5981 args[arg] = args[arg+1]; // shift args after inversion
5982 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005983
William Lallemand0f99e342011-10-12 17:50:54 +02005984 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5985 strcmp(args[0], "log") != 0) {
5986 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005987 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005988 }
5989
Willy Tarreau977b8e42006-12-29 14:19:17 +01005990 if (!strcmp(args[0], "listen") ||
5991 !strcmp(args[0], "frontend") ||
5992 !strcmp(args[0], "backend") ||
5993 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005994 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005996 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005997 cursection = strdup(args[0]);
5998 }
5999 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006000 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006001 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006002 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006003 }
6004 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006005 confsect = CFG_USERLIST;
6006 free(cursection);
6007 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006008 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006009 else if (!strcmp(args[0], "peers")) {
6010 confsect = CFG_PEERS;
6011 free(cursection);
6012 cursection = strdup(args[0]);
6013 }
6014
Willy Tarreaubaaee002006-06-26 02:48:02 +02006015 /* else it's a section keyword */
6016
6017 switch (confsect) {
6018 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006019 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006020 break;
6021 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006022 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006023 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006024 case CFG_USERLIST:
6025 err_code |= cfg_parse_users(file, linenum, args, kwm);
6026 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006027 case CFG_PEERS:
6028 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6029 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006030 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006031 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006032 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006034
6035 if (err_code & ERR_ABORT)
6036 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006037 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006038 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006039 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006040 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006041 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006042}
6043
Willy Tarreaubb925012009-07-23 13:36:36 +02006044/*
6045 * Returns the error code, 0 if OK, or any combination of :
6046 * - ERR_ABORT: must abort ASAP
6047 * - ERR_FATAL: we can continue parsing but not start the service
6048 * - ERR_WARN: a warning has been emitted
6049 * - ERR_ALERT: an alert has been emitted
6050 * Only the two first ones can stop processing, the two others are just
6051 * indicators.
6052 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006053int check_config_validity()
6054{
6055 int cfgerr = 0;
6056 struct proxy *curproxy = NULL;
6057 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006058 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006059 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006060 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006061 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006062
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006063 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006064 /*
6065 * Now, check for the integrity of all that we have collected.
6066 */
6067
6068 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006069 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006070
Willy Tarreau193b8c62012-11-22 00:17:38 +01006071 if (!global.tune.max_http_hdr)
6072 global.tune.max_http_hdr = MAX_HTTP_HDR;
6073
6074 if (!global.tune.cookie_len)
6075 global.tune.cookie_len = CAPTURE_LEN;
6076
6077 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6078
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006079 /* first, we will invert the proxy list order */
6080 curproxy = NULL;
6081 while (proxy) {
6082 struct proxy *next;
6083
6084 next = proxy->next;
6085 proxy->next = curproxy;
6086 curproxy = proxy;
6087 if (!next)
6088 break;
6089 proxy = next;
6090 }
6091
Willy Tarreaubaaee002006-06-26 02:48:02 +02006092 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006093 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006094 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006095 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006096 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006097 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006098 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006099 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006100
Willy Tarreau050536d2012-10-04 08:47:34 +02006101 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006102 /* proxy ID not set, use automatic numbering with first
6103 * spare entry starting with next_pxid.
6104 */
6105 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6106 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6107 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006108 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006109 next_pxid++;
6110
Willy Tarreau55ea7572007-06-17 19:56:27 +02006111
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006113 /* ensure we don't keep listeners uselessly bound */
6114 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006115 curproxy = curproxy->next;
6116 continue;
6117 }
6118
Willy Tarreau16a21472012-11-19 12:39:59 +01006119 /* number of processes this proxy is bound to */
6120 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6121
Willy Tarreauff01a212009-03-15 13:46:16 +01006122 switch (curproxy->mode) {
6123 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006124 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006125 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006126 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6127 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006128 cfgerr++;
6129 }
6130
6131 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006132 Warning("config : servers will be ignored for %s '%s'.\n",
6133 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006134 break;
6135
6136 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006137 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006138 break;
6139
6140 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006141 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006142 break;
6143 }
6144
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006145 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006146 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006147 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006148 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6149 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006150 cfgerr++;
6151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006152#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006153 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006154 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6155 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006156 cfgerr++;
6157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006158#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006159 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006160 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6161 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006162 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006163 }
6164 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006165 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006166 /* If no LB algo is set in a backend, and we're not in
6167 * transparent mode, dispatch mode nor proxy mode, we
6168 * want to use balance roundrobin by default.
6169 */
6170 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6171 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 }
6173 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006174
Willy Tarreau1620ec32011-08-06 17:05:02 +02006175 if (curproxy->options & PR_O_DISPATCH)
6176 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6177 else if (curproxy->options & PR_O_HTTP_PROXY)
6178 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6179 else if (curproxy->options & PR_O_TRANSP)
6180 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006181
Willy Tarreau1620ec32011-08-06 17:05:02 +02006182 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6183 if (curproxy->options & PR_O_DISABLE404) {
6184 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6185 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6186 err_code |= ERR_WARN;
6187 curproxy->options &= ~PR_O_DISABLE404;
6188 }
6189 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6190 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6191 "send-state", proxy_type_str(curproxy), curproxy->id);
6192 err_code |= ERR_WARN;
6193 curproxy->options &= ~PR_O2_CHK_SNDST;
6194 }
Willy Tarreauef781042010-01-27 11:53:01 +01006195 }
6196
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006197 /* if a default backend was specified, let's find it */
6198 if (curproxy->defbe.name) {
6199 struct proxy *target;
6200
Alex Williams96532db2009-11-01 21:27:13 -05006201 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006202 if (!target) {
6203 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6204 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006205 cfgerr++;
6206 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006207 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6208 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006209 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006210 } else {
6211 free(curproxy->defbe.name);
6212 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006213 /* we force the backend to be present on at least all of
6214 * the frontend's processes.
6215 */
6216 target->bind_proc = curproxy->bind_proc ?
6217 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006218
6219 /* Emit a warning if this proxy also has some servers */
6220 if (curproxy->srv) {
6221 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6222 curproxy->id);
6223 err_code |= ERR_WARN;
6224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006225 }
6226 }
6227
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006228 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006229 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6230 /* map jump target for ACT_SETBE in req_rep chain */
6231 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006232 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006233 struct proxy *target;
6234
Willy Tarreaua496b602006-12-17 23:15:24 +01006235 if (exp->action != ACT_SETBE)
6236 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006237
Alex Williams96532db2009-11-01 21:27:13 -05006238 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006239 if (!target) {
6240 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6241 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006242 cfgerr++;
6243 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006244 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6245 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006246 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006247 } else {
6248 free((void *)exp->replace);
6249 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006250 /* we force the backend to be present on at least all of
6251 * the frontend's processes.
6252 */
6253 target->bind_proc = curproxy->bind_proc ?
6254 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006255 }
6256 }
6257 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006258
6259 /* find the target proxy for 'use_backend' rules */
6260 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006261 struct proxy *target;
6262
Alex Williams96532db2009-11-01 21:27:13 -05006263 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006264
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006265 if (!target) {
6266 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6267 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006268 cfgerr++;
6269 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006270 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6271 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006272 cfgerr++;
6273 } else {
6274 free((void *)rule->be.name);
6275 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006276 /* we force the backend to be present on at least all of
6277 * the frontend's processes.
6278 */
6279 target->bind_proc = curproxy->bind_proc ?
6280 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006281 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006282 }
6283
6284 /* find the target proxy for 'use_backend' rules */
6285 list_for_each_entry(srule, &curproxy->server_rules, list) {
6286 struct server *target = findserver(curproxy, srule->srv.name);
6287
6288 if (!target) {
6289 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6290 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6291 cfgerr++;
6292 continue;
6293 }
6294 free((void *)srule->srv.name);
6295 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006296 }
6297
Emeric Brunb982a3d2010-01-04 15:45:53 +01006298 /* find the target table for 'stick' rules */
6299 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6300 struct proxy *target;
6301
Emeric Brun1d33b292010-01-04 15:47:17 +01006302 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6303 if (mrule->flags & STK_IS_STORE)
6304 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6305
Emeric Brunb982a3d2010-01-04 15:45:53 +01006306 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006307 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006308 else
6309 target = curproxy;
6310
6311 if (!target) {
6312 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6313 curproxy->id, mrule->table.name);
6314 cfgerr++;
6315 }
6316 else if (target->table.size == 0) {
6317 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6318 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6319 cfgerr++;
6320 }
Willy Tarreau12785782012-04-27 21:37:17 +02006321 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6322 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006323 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6324 cfgerr++;
6325 }
6326 else {
6327 free((void *)mrule->table.name);
6328 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006329 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006330 }
6331 }
6332
6333 /* find the target table for 'store response' rules */
6334 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6335 struct proxy *target;
6336
Emeric Brun1d33b292010-01-04 15:47:17 +01006337 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6338
Emeric Brunb982a3d2010-01-04 15:45:53 +01006339 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006340 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006341 else
6342 target = curproxy;
6343
6344 if (!target) {
6345 Alert("Proxy '%s': unable to find store table '%s'.\n",
6346 curproxy->id, mrule->table.name);
6347 cfgerr++;
6348 }
6349 else if (target->table.size == 0) {
6350 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6351 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6352 cfgerr++;
6353 }
Willy Tarreau12785782012-04-27 21:37:17 +02006354 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6355 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006356 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6357 cfgerr++;
6358 }
6359 else {
6360 free((void *)mrule->table.name);
6361 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006362 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006363 }
6364 }
6365
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006366 /* find the target table for 'tcp-request' layer 4 rules */
6367 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6368 struct proxy *target;
6369
Willy Tarreaube4a3ef2013-06-17 15:04:07 +02006370 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006371 continue;
6372
6373 if (trule->act_prm.trk_ctr.table.n)
6374 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6375 else
6376 target = curproxy;
6377
6378 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006379 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6380 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006381 1 + tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006382 cfgerr++;
6383 }
6384 else if (target->table.size == 0) {
6385 Alert("Proxy '%s': table '%s' used but not configured.\n",
6386 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6387 cfgerr++;
6388 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006389 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6390 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6391 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006392 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006393 cfgerr++;
6394 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006395 else {
6396 free(trule->act_prm.trk_ctr.table.n);
6397 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006398 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006399 * to pass a list of counters to track and allocate them right here using
6400 * stktable_alloc_data_type().
6401 */
6402 }
6403 }
6404
Willy Tarreaud1f96522010-08-03 19:34:32 +02006405 /* find the target table for 'tcp-request' layer 6 rules */
6406 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6407 struct proxy *target;
6408
Willy Tarreaube4a3ef2013-06-17 15:04:07 +02006409 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006410 continue;
6411
6412 if (trule->act_prm.trk_ctr.table.n)
6413 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6414 else
6415 target = curproxy;
6416
6417 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006418 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6419 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006420 1 + tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006421 cfgerr++;
6422 }
6423 else if (target->table.size == 0) {
6424 Alert("Proxy '%s': table '%s' used but not configured.\n",
6425 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6426 cfgerr++;
6427 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006428 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6429 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6430 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006431 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006432 cfgerr++;
6433 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006434 else {
6435 free(trule->act_prm.trk_ctr.table.n);
6436 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006437 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006438 * to pass a list of counters to track and allocate them right here using
6439 * stktable_alloc_data_type().
6440 */
6441 }
6442 }
6443
Emeric Brun32da3c42010-09-23 18:39:19 +02006444 if (curproxy->table.peers.name) {
6445 struct peers *curpeers = peers;
6446
6447 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6448 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6449 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006450 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006451 break;
6452 }
6453 }
6454
6455 if (!curpeers) {
6456 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6457 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006458 free((void *)curproxy->table.peers.name);
6459 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006460 cfgerr++;
6461 }
6462 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006463 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6464 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006465 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006466 cfgerr++;
6467 }
6468 }
6469
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006470 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006471 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006472 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6473 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6474 "proxy", curproxy->id);
6475 cfgerr++;
6476 goto out_uri_auth_compat;
6477 }
6478
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006479 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006480 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006481 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006482 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006483
Willy Tarreau95fa4692010-02-01 13:05:50 +01006484 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6485 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006486
6487 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006488 uri_auth_compat_req[i++] = "realm";
6489 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6490 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006491
Willy Tarreau95fa4692010-02-01 13:05:50 +01006492 uri_auth_compat_req[i++] = "unless";
6493 uri_auth_compat_req[i++] = "{";
6494 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6495 uri_auth_compat_req[i++] = "}";
6496 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006497
Willy Tarreauff011f22011-01-06 17:51:27 +01006498 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6499 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006500 cfgerr++;
6501 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006502 }
6503
Willy Tarreauff011f22011-01-06 17:51:27 +01006504 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006505
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006506 if (curproxy->uri_auth->auth_realm) {
6507 free(curproxy->uri_auth->auth_realm);
6508 curproxy->uri_auth->auth_realm = NULL;
6509 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006510
6511 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006512 }
6513out_uri_auth_compat:
6514
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006515 /* compile the log format */
6516 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006517 if (curproxy->conf.logformat_string != default_http_log_format &&
6518 curproxy->conf.logformat_string != default_tcp_log_format &&
6519 curproxy->conf.logformat_string != clf_http_log_format)
6520 free(curproxy->conf.logformat_string);
6521 curproxy->conf.logformat_string = NULL;
6522 free(curproxy->conf.lfs_file);
6523 curproxy->conf.lfs_file = NULL;
6524 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006525 }
6526
Willy Tarreau62a61232013-04-12 18:13:46 +02006527 if (curproxy->conf.logformat_string) {
6528 curproxy->conf.args.ctx = ARGC_LOG;
6529 curproxy->conf.args.file = curproxy->conf.lfs_file;
6530 curproxy->conf.args.line = curproxy->conf.lfs_line;
6531 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006532 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006533 curproxy->conf.args.file = NULL;
6534 curproxy->conf.args.line = 0;
6535 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006536
Willy Tarreau62a61232013-04-12 18:13:46 +02006537 if (curproxy->conf.uniqueid_format_string) {
6538 curproxy->conf.args.ctx = ARGC_UIF;
6539 curproxy->conf.args.file = curproxy->conf.uif_file;
6540 curproxy->conf.args.line = curproxy->conf.uif_line;
6541 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006542 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006543 curproxy->conf.args.file = NULL;
6544 curproxy->conf.args.line = 0;
6545 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006546
6547 /* only now we can check if some args remain unresolved */
6548 cfgerr += smp_resolve_args(curproxy);
6549 if (!cfgerr)
6550 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006551
Willy Tarreau2738a142006-07-08 17:28:09 +02006552 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006553 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006554 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006555 (!curproxy->timeout.connect ||
6556 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006557 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006558 " | While not properly invalid, you will certainly encounter various problems\n"
6559 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006560 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006561 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006562 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006563 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006564
Willy Tarreau1fa31262007-12-03 00:36:16 +01006565 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6566 * We must still support older configurations, so let's find out whether those
6567 * parameters have been set or must be copied from contimeouts.
6568 */
6569 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006570 if (!curproxy->timeout.tarpit ||
6571 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006572 /* tarpit timeout not set. We search in the following order:
6573 * default.tarpit, curr.connect, default.connect.
6574 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006575 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006576 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006577 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006578 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006579 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006580 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006581 }
6582 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006583 (!curproxy->timeout.queue ||
6584 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006585 /* queue timeout not set. We search in the following order:
6586 * default.queue, curr.connect, default.connect.
6587 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006588 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006589 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006590 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006591 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006592 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006593 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006594 }
6595 }
6596
Willy Tarreau1620ec32011-08-06 17:05:02 +02006597 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006598 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6599 curproxy->check_req = (char *)malloc(curproxy->check_len);
6600 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006601 }
6602
Willy Tarreau193b8c62012-11-22 00:17:38 +01006603 /* ensure that cookie capture length is not too large */
6604 if (curproxy->capture_len >= global.tune.cookie_len) {
6605 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6606 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6607 err_code |= ERR_WARN;
6608 curproxy->capture_len = global.tune.cookie_len - 1;
6609 }
6610
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006611 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006612 if (curproxy->nb_req_cap) {
6613 if (curproxy->mode == PR_MODE_HTTP) {
6614 curproxy->req_cap_pool = create_pool("ptrcap",
6615 curproxy->nb_req_cap * sizeof(char *),
6616 MEM_F_SHARED);
6617 } else {
6618 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6619 proxy_type_str(curproxy), curproxy->id);
6620 err_code |= ERR_WARN;
6621 curproxy->to_log &= ~LW_REQHDR;
6622 curproxy->nb_req_cap = 0;
6623 }
6624 }
6625
6626 if (curproxy->nb_rsp_cap) {
6627 if (curproxy->mode == PR_MODE_HTTP) {
6628 curproxy->rsp_cap_pool = create_pool("ptrcap",
6629 curproxy->nb_rsp_cap * sizeof(char *),
6630 MEM_F_SHARED);
6631 } else {
6632 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6633 proxy_type_str(curproxy), curproxy->id);
6634 err_code |= ERR_WARN;
6635 curproxy->to_log &= ~LW_REQHDR;
6636 curproxy->nb_rsp_cap = 0;
6637 }
6638 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006639
Willy Tarreaubaaee002006-06-26 02:48:02 +02006640 /* first, we will invert the servers list order */
6641 newsrv = NULL;
6642 while (curproxy->srv) {
6643 struct server *next;
6644
6645 next = curproxy->srv->next;
6646 curproxy->srv->next = newsrv;
6647 newsrv = curproxy->srv;
6648 if (!next)
6649 break;
6650 curproxy->srv = next;
6651 }
6652
Willy Tarreaudd701652010-05-25 23:03:02 +02006653 /* assign automatic UIDs to servers which don't have one yet */
6654 next_id = 1;
6655 newsrv = curproxy->srv;
6656 while (newsrv != NULL) {
6657 if (!newsrv->puid) {
6658 /* server ID not set, use automatic numbering with first
6659 * spare entry starting with next_svid.
6660 */
6661 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6662 newsrv->conf.id.key = newsrv->puid = next_id;
6663 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6664 }
6665 next_id++;
6666 newsrv = newsrv->next;
6667 }
6668
Willy Tarreau20697042007-11-15 23:26:18 +01006669 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006670 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006671
Willy Tarreau62c3be22012-01-20 13:12:32 +01006672 /*
6673 * If this server supports a maxconn parameter, it needs a dedicated
6674 * tasks to fill the emptied slots when a connection leaves.
6675 * Also, resolve deferred tracking dependency if needed.
6676 */
6677 newsrv = curproxy->srv;
6678 while (newsrv != NULL) {
6679 if (newsrv->minconn > newsrv->maxconn) {
6680 /* Only 'minconn' was specified, or it was higher than or equal
6681 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6682 * this will avoid further useless expensive computations.
6683 */
6684 newsrv->maxconn = newsrv->minconn;
6685 } else if (newsrv->maxconn && !newsrv->minconn) {
6686 /* minconn was not specified, so we set it to maxconn */
6687 newsrv->minconn = newsrv->maxconn;
6688 }
6689
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006690#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006691 if (newsrv->use_ssl || newsrv->check.use_ssl)
6692 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006693#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006694
Willy Tarreau62c3be22012-01-20 13:12:32 +01006695 if (newsrv->trackit) {
6696 struct proxy *px;
6697 struct server *srv;
6698 char *pname, *sname;
6699
6700 pname = newsrv->trackit;
6701 sname = strrchr(pname, '/');
6702
6703 if (sname)
6704 *sname++ = '\0';
6705 else {
6706 sname = pname;
6707 pname = NULL;
6708 }
6709
6710 if (pname) {
6711 px = findproxy(pname, PR_CAP_BE);
6712 if (!px) {
6713 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6714 proxy_type_str(curproxy), curproxy->id,
6715 newsrv->id, pname);
6716 cfgerr++;
6717 goto next_srv;
6718 }
6719 } else
6720 px = curproxy;
6721
6722 srv = findserver(px, sname);
6723 if (!srv) {
6724 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6725 proxy_type_str(curproxy), curproxy->id,
6726 newsrv->id, sname);
6727 cfgerr++;
6728 goto next_srv;
6729 }
6730
6731 if (!(srv->state & SRV_CHECKED)) {
6732 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6733 "tracking as it does not have checks enabled.\n",
6734 proxy_type_str(curproxy), curproxy->id,
6735 newsrv->id, px->id, srv->id);
6736 cfgerr++;
6737 goto next_srv;
6738 }
6739
6740 if (curproxy != px &&
6741 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6742 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6743 "tracking: disable-on-404 option inconsistency.\n",
6744 proxy_type_str(curproxy), curproxy->id,
6745 newsrv->id, px->id, srv->id);
6746 cfgerr++;
6747 goto next_srv;
6748 }
6749
6750 /* if the other server is forced disabled, we have to do the same here */
6751 if (srv->state & SRV_MAINTAIN) {
6752 newsrv->state |= SRV_MAINTAIN;
6753 newsrv->state &= ~SRV_RUNNING;
6754 newsrv->health = 0;
6755 }
6756
6757 newsrv->track = srv;
6758 newsrv->tracknext = srv->tracknext;
6759 srv->tracknext = newsrv;
6760
6761 free(newsrv->trackit);
6762 newsrv->trackit = NULL;
6763 }
6764 next_srv:
6765 newsrv = newsrv->next;
6766 }
6767
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006768 /* We have to initialize the server lookup mechanism depending
6769 * on what LB algorithm was choosen.
6770 */
6771
6772 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6773 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6774 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006775 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6776 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6777 init_server_map(curproxy);
6778 } else {
6779 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6780 fwrr_init_server_groups(curproxy);
6781 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006782 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006783
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006784 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006785 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6786 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6787 fwlc_init_server_tree(curproxy);
6788 } else {
6789 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6790 fas_init_server_tree(curproxy);
6791 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006792 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006793
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006794 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006795 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6796 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6797 chash_init_server_tree(curproxy);
6798 } else {
6799 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6800 init_server_map(curproxy);
6801 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006802 break;
6803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006804
6805 if (curproxy->options & PR_O_LOGASAP)
6806 curproxy->to_log &= ~LW_BYTES;
6807
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006808 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006809 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006810 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6811 proxy_type_str(curproxy), curproxy->id);
6812 err_code |= ERR_WARN;
6813 }
6814
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006815 if (curproxy->mode != PR_MODE_HTTP) {
6816 int optnum;
6817
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006818 if (curproxy->uri_auth) {
6819 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6820 proxy_type_str(curproxy), curproxy->id);
6821 err_code |= ERR_WARN;
6822 curproxy->uri_auth = NULL;
6823 }
6824
Willy Tarreau87cf5142011-08-19 22:57:24 +02006825 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006826 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6827 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6828 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006829 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006830 }
6831
6832 if (curproxy->options & PR_O_ORGTO) {
6833 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6834 "originalto", proxy_type_str(curproxy), curproxy->id);
6835 err_code |= ERR_WARN;
6836 curproxy->options &= ~PR_O_ORGTO;
6837 }
6838
6839 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6840 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6841 (curproxy->cap & cfg_opts[optnum].cap) &&
6842 (curproxy->options & cfg_opts[optnum].val)) {
6843 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6844 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6845 err_code |= ERR_WARN;
6846 curproxy->options &= ~cfg_opts[optnum].val;
6847 }
6848 }
6849
6850 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6851 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6852 (curproxy->cap & cfg_opts2[optnum].cap) &&
6853 (curproxy->options2 & cfg_opts2[optnum].val)) {
6854 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6855 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6856 err_code |= ERR_WARN;
6857 curproxy->options2 &= ~cfg_opts2[optnum].val;
6858 }
6859 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006860
Pieter Baauwd551fb52013-05-08 22:49:23 +02006861#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006862 if (curproxy->conn_src.bind_hdr_occ) {
6863 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006864 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006865 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006866 err_code |= ERR_WARN;
6867 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006868#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006869 }
6870
Willy Tarreaubaaee002006-06-26 02:48:02 +02006871 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006872 * ensure that we're not cross-dressing a TCP server into HTTP.
6873 */
6874 newsrv = curproxy->srv;
6875 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006876 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006877 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6878 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006879 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006880 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006881
Willy Tarreau0cec3312011-10-31 13:49:26 +01006882 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6883 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6884 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6885 err_code |= ERR_WARN;
6886 }
6887
Pieter Baauwd551fb52013-05-08 22:49:23 +02006888#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006889 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6890 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006891 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 +01006892 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006893 err_code |= ERR_WARN;
6894 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006895#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006896 newsrv = newsrv->next;
6897 }
6898
Willy Tarreauc1a21672009-08-16 22:37:44 +02006899 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006900 if (!curproxy->accept)
6901 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006902
Willy Tarreauc1a21672009-08-16 22:37:44 +02006903 if (curproxy->tcp_req.inspect_delay ||
6904 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006905 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006906
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006907 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006908 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006909 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006910 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006911
6912 /* both TCP and HTTP must check switching rules */
6913 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6914 }
6915
6916 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006917 if (curproxy->tcp_req.inspect_delay ||
6918 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6919 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6920
Emeric Brun97679e72010-09-23 17:56:44 +02006921 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6922 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6923
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006924 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006925 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006926 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006927 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006928
6929 /* If the backend does requires RDP cookie persistence, we have to
6930 * enable the corresponding analyser.
6931 */
6932 if (curproxy->options2 & PR_O2_RDPC_PRST)
6933 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6934 }
6935
Emeric Brunc52962f2012-11-15 18:28:02 +01006936#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006937 /* Configure SSL for each bind line.
6938 * Note: if configuration fails at some point, the ->ctx member
6939 * remains NULL so that listeners can later detach.
6940 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006941 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006942 if (!bind_conf->is_ssl) {
6943 if (bind_conf->default_ctx) {
6944 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6945 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6946 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006947 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006948 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006949 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006950 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006951 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006952 cfgerr++;
6953 continue;
6954 }
6955
Emeric Brun4b3091e2012-09-24 15:48:52 +02006956 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006957 Alert("Unable to allocate SSL session cache.\n");
6958 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006959 continue;
6960 }
6961
Emeric Brunfc0421f2012-09-07 17:30:07 +02006962 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006963 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006964 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006965#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006966
Willy Tarreaue6b98942007-10-29 01:09:36 +01006967 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006968 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006969 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006970 if (!listener->luid) {
6971 /* listener ID not set, use automatic numbering with first
6972 * spare entry starting with next_luid.
6973 */
6974 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6975 listener->conf.id.key = listener->luid = next_id;
6976 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006977 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006978 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006979
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006980 /* enable separate counters */
6981 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6982 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006983 if (!listener->name)
6984 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006985 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006986
Willy Tarreaue6b98942007-10-29 01:09:36 +01006987 if (curproxy->options & PR_O_TCP_NOLING)
6988 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006989 if (!listener->maxconn)
6990 listener->maxconn = curproxy->maxconn;
6991 if (!listener->backlog)
6992 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006993 if (!listener->maxaccept)
6994 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6995
6996 /* we want to have an optimal behaviour on single process mode to
6997 * maximize the work at once, but in multi-process we want to keep
6998 * some fairness between processes, so we target half of the max
6999 * number of events to be balanced over all the processes the proxy
7000 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7001 * used to disable the limit.
7002 */
7003 if (listener->maxaccept > 0) {
7004 if (nbproc > 1)
7005 listener->maxaccept = (listener->maxaccept + 1) / 2;
7006 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7007 }
7008
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007009 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007010 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007011 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007012 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007013
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007014 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7015 listener->options |= LI_O_TCP_RULES;
7016
Willy Tarreaude3041d2010-05-31 10:56:17 +02007017 if (curproxy->mon_mask.s_addr)
7018 listener->options |= LI_O_CHK_MONNET;
7019
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007020 /* smart accept mode is automatic in HTTP mode */
7021 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007022 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007023 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7024 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007025 }
7026
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007027 /* Release unused SSL configs */
7028 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7029 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007030 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007031#ifdef USE_OPENSSL
7032 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007033 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007034 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007035 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007036 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007037#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007038 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007039
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007040 /* Check multi-process mode compatibility for the current proxy */
7041 if (global.nbproc > 1) {
7042 int nbproc = 0;
7043 if (curproxy->bind_proc) {
7044 int proc;
7045 for (proc = 0; proc < global.nbproc; proc++) {
7046 if (curproxy->bind_proc & (1 << proc)) {
7047 nbproc++;
7048 }
7049 }
7050 } else {
7051 nbproc = global.nbproc;
7052 }
7053 if (curproxy->table.peers.name) {
7054 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7055 curproxy->id);
7056 cfgerr++;
7057 }
7058 if (nbproc > 1) {
7059 if (curproxy->uri_auth) {
7060 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7061 curproxy->id);
7062 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7063 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7064 curproxy->id);
7065 }
7066 }
7067 if (curproxy->appsession_name) {
7068 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7069 curproxy->id);
7070 }
7071 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7072 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7073 curproxy->id);
7074 }
7075 }
7076 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007077
7078 /* create the task associated with the proxy */
7079 curproxy->task = task_new();
7080 if (curproxy->task) {
7081 curproxy->task->context = curproxy;
7082 curproxy->task->process = manage_proxy;
7083 /* no need to queue, it will be done automatically if some
7084 * listener gets limited.
7085 */
7086 curproxy->task->expire = TICK_ETERNITY;
7087 } else {
7088 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7089 curproxy->id);
7090 cfgerr++;
7091 }
7092
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093 curproxy = curproxy->next;
7094 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007095
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007096 /* Check multi-process mode compatibility */
7097 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007098 if (global.stats_fe && !global.stats_fe->bind_proc) {
7099 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 +01007100 }
7101 }
7102
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007103 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7104 struct auth_users *curuser;
7105 int g;
7106
7107 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7108 unsigned int group_mask = 0;
7109 char *group = NULL;
7110
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007111 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007112 continue;
7113
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007114 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007115
7116 for (g = 0; g < curuserlist->grpcnt; g++)
7117 if (!strcmp(curuserlist->groups[g], group))
7118 break;
7119
7120 if (g == curuserlist->grpcnt) {
7121 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7122 curuserlist->name, group, curuser->user);
7123 err_code |= ERR_ALERT | ERR_FATAL;
7124 goto out;
7125 }
7126
7127 group_mask |= (1 << g);
7128 }
7129
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007130 free(curuser->u.groups);
7131 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007132 }
7133
7134 for (g = 0; g < curuserlist->grpcnt; g++) {
7135 char *user = NULL;
7136
7137 if (!curuserlist->groupusers[g])
7138 continue;
7139
7140 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7141 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7142 if (!strcmp(curuser->user, user))
7143 break;
7144
7145 if (!curuser) {
7146 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7147 curuserlist->name, user, curuserlist->groups[g]);
7148 err_code |= ERR_ALERT | ERR_FATAL;
7149 goto out;
7150 }
7151
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007152 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007153 }
7154
7155 free(curuserlist->groupusers[g]);
7156 }
7157
7158 free(curuserlist->groupusers);
7159
7160#ifdef DEBUG_AUTH
7161 for (g = 0; g < curuserlist->grpcnt; g++) {
7162 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7163
7164 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007165 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007166 fprintf(stderr, " %s", curuser->user);
7167 }
7168
7169 fprintf(stderr, "\n");
7170 }
7171#endif
7172
Willy Tarreaufbb78422011-06-05 15:38:35 +02007173 }
7174
7175 /* automatically compute fullconn if not set. We must not do it in the
7176 * loop above because cross-references are not yet fully resolved.
7177 */
7178 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7179 /* If <fullconn> is not set, let's set it to 10% of the sum of
7180 * the possible incoming frontend's maxconns.
7181 */
7182 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7183 struct proxy *fe;
7184 int total = 0;
7185
7186 /* sum up the number of maxconns of frontends which
7187 * reference this backend at least once or which are
7188 * the same one ('listen').
7189 */
7190 for (fe = proxy; fe; fe = fe->next) {
7191 struct switching_rule *rule;
7192 struct hdr_exp *exp;
7193 int found = 0;
7194
7195 if (!(fe->cap & PR_CAP_FE))
7196 continue;
7197
7198 if (fe == curproxy) /* we're on a "listen" instance */
7199 found = 1;
7200
7201 if (fe->defbe.be == curproxy) /* "default_backend" */
7202 found = 1;
7203
7204 /* check if a "use_backend" rule matches */
7205 if (!found) {
7206 list_for_each_entry(rule, &fe->switching_rules, list) {
7207 if (rule->be.backend == curproxy) {
7208 found = 1;
7209 break;
7210 }
7211 }
7212 }
7213
7214 /* check if a "reqsetbe" rule matches */
7215 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7216 if (exp->action == ACT_SETBE &&
7217 (struct proxy *)exp->replace == curproxy) {
7218 found = 1;
7219 break;
7220 }
7221 }
7222
7223 /* now we've checked all possible ways to reference a backend
7224 * from a frontend.
7225 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007226 if (!found)
7227 continue;
7228 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007229 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007230 /* we have the sum of the maxconns in <total>. We only
7231 * keep 10% of that sum to set the default fullconn, with
7232 * a hard minimum of 1 (to avoid a divide by zero).
7233 */
7234 curproxy->fullconn = (total + 9) / 10;
7235 if (!curproxy->fullconn)
7236 curproxy->fullconn = 1;
7237 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007238 }
7239
Willy Tarreau056f5682010-06-06 15:51:11 +02007240 /* initialize stick-tables on backend capable proxies. This must not
7241 * be done earlier because the data size may be discovered while parsing
7242 * other proxies.
7243 */
7244 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007245 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007246
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007247 /*
7248 * Recount currently required checks.
7249 */
7250
7251 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7252 int optnum;
7253
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007254 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7255 if (curproxy->options & cfg_opts[optnum].val)
7256 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007257
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007258 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7259 if (curproxy->options2 & cfg_opts2[optnum].val)
7260 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007261 }
7262
Willy Tarreau122541c2011-09-07 21:24:49 +02007263 if (peers) {
7264 struct peers *curpeers = peers, **last;
7265 struct peer *p, *pb;
7266
7267 /* Remove all peers sections which don't have a valid listener.
7268 * This can happen when a peers section is never referenced and
7269 * does not contain a local peer.
7270 */
7271 last = &peers;
7272 while (*last) {
7273 curpeers = *last;
7274 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007275 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007276 last = &curpeers->next;
7277 continue;
7278 }
7279
7280 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7281 curpeers->id, localpeer);
7282
7283 p = curpeers->remote;
7284 while (p) {
7285 pb = p->next;
7286 free(p->id);
7287 free(p);
7288 p = pb;
7289 }
7290
7291 /* Destroy and unlink this curpeers section.
7292 * Note: curpeers is backed up into *last.
7293 */
7294 free(curpeers->id);
7295 curpeers = curpeers->next;
7296 free(*last);
7297 *last = curpeers;
7298 }
7299 }
7300
Willy Tarreau34eb6712011-10-24 18:15:04 +02007301 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007302 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007303 MEM_F_SHARED);
7304
Willy Tarreaubb925012009-07-23 13:36:36 +02007305 if (cfgerr > 0)
7306 err_code |= ERR_ALERT | ERR_FATAL;
7307 out:
7308 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007309}
7310
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007311/*
7312 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7313 * parsing sessions.
7314 */
7315void cfg_register_keywords(struct cfg_kw_list *kwl)
7316{
7317 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7318}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007319
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007320/*
7321 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7322 */
7323void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7324{
7325 LIST_DEL(&kwl->list);
7326 LIST_INIT(&kwl->list);
7327}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007328
7329/*
7330 * Local variables:
7331 * c-indent-level: 8
7332 * c-basic-offset: 8
7333 * End:
7334 */