blob: b82a2dc68423cecf10f86bbdef5685b459c4cf69 [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 Tarreau8b8fd562013-01-18 11:12:27 +01001575 curpeers->peers_fe->conf.file = strdup(file);
1576 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 Tarreau8113a5d2012-10-04 08:01:43 +02001695 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001696 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001697 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001699 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700
1701 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001703 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001704
Willy Tarreau4348fad2012-09-20 16:48:07 +02001705 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1706
Willy Tarreau902636f2013-03-10 19:44:48 +01001707 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1708 if (errmsg && *errmsg) {
1709 indent_msg(&errmsg, 2);
1710 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001711 }
1712 else
1713 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1714 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001715 err_code |= ERR_FATAL;
1716 goto out;
1717 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001718
Willy Tarreau4348fad2012-09-20 16:48:07 +02001719 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001720 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 }
1723
1724 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001725 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001726 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001727
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001730 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001731 curproxy->no_options = defproxy.no_options;
1732 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001733 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001734 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001735 curproxy->except_net = defproxy.except_net;
1736 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001737 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001738 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001740 if (defproxy.fwdfor_hdr_len) {
1741 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1742 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1743 }
1744
Willy Tarreaub86db342009-11-30 11:50:16 +01001745 if (defproxy.orgto_hdr_len) {
1746 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1747 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1748 }
1749
Mark Lamourinec2247f02012-01-04 13:02:01 -05001750 if (defproxy.server_id_hdr_len) {
1751 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1752 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1753 }
1754
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 if (curproxy->cap & PR_CAP_FE) {
1756 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001757 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001758 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001759
1760 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001761 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1762 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763
1764 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766
Willy Tarreau977b8e42006-12-29 14:19:17 +01001767 if (curproxy->cap & PR_CAP_BE) {
1768 curproxy->fullconn = defproxy.fullconn;
1769 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001771 if (defproxy.check_req) {
1772 curproxy->check_req = calloc(1, defproxy.check_len);
1773 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1774 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001775 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001777 if (defproxy.expect_str) {
1778 curproxy->expect_str = strdup(defproxy.expect_str);
1779 if (defproxy.expect_regex) {
1780 /* note: this regex is known to be valid */
1781 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1782 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1783 }
1784 }
1785
Willy Tarreau67402132012-05-31 20:40:20 +02001786 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 if (defproxy.cookie_name)
1788 curproxy->cookie_name = strdup(defproxy.cookie_name);
1789 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001790 if (defproxy.cookie_domain)
1791 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001792
Willy Tarreau31936852010-10-06 16:59:56 +02001793 if (defproxy.cookie_maxidle)
1794 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1795
1796 if (defproxy.cookie_maxlife)
1797 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1798
Emeric Brun647caf12009-06-30 17:57:00 +02001799 if (defproxy.rdp_cookie_name)
1800 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1801 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1802
Willy Tarreau01732802007-11-01 22:48:15 +01001803 if (defproxy.url_param_name)
1804 curproxy->url_param_name = strdup(defproxy.url_param_name);
1805 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001806
Benoitaffb4812009-03-25 13:02:10 +01001807 if (defproxy.hh_name)
1808 curproxy->hh_name = strdup(defproxy.hh_name);
1809 curproxy->hh_len = defproxy.hh_len;
1810 curproxy->hh_match_domain = defproxy.hh_match_domain;
1811
Willy Tarreauef9a3602012-12-08 22:29:20 +01001812 if (defproxy.conn_src.iface_name)
1813 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1814 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1815 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001818 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001819 if (defproxy.capture_name)
1820 curproxy->capture_name = strdup(defproxy.capture_name);
1821 curproxy->capture_namelen = defproxy.capture_namelen;
1822 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001823 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001824
Willy Tarreau977b8e42006-12-29 14:19:17 +01001825 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001826 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001827 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001828 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001829 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001830 curproxy->uri_auth = defproxy.uri_auth;
1831 curproxy->mon_net = defproxy.mon_net;
1832 curproxy->mon_mask = defproxy.mon_mask;
1833 if (defproxy.monitor_uri)
1834 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1835 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001836 if (defproxy.defbe.name)
1837 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001838
1839 /* get either a pointer to the logformat string or a copy of it */
1840 curproxy->logformat_string = defproxy.logformat_string;
1841 if (curproxy->logformat_string &&
1842 curproxy->logformat_string != default_http_log_format &&
1843 curproxy->logformat_string != default_tcp_log_format &&
1844 curproxy->logformat_string != clf_http_log_format)
1845 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001846 }
1847
1848 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001849 curproxy->timeout.connect = defproxy.timeout.connect;
1850 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001851 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001852 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001853 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001854 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001855 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001856 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001857 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001858 }
1859
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001861
1862 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001863 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001864 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001865 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001866 LIST_INIT(&node->list);
1867 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1868 }
1869
Willy Tarreau196729e2012-05-31 19:30:26 +02001870 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1871 if (curproxy->uniqueid_format_string)
1872 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001873
1874 /* copy default header unique id */
1875 if (defproxy.header_unique_id)
1876 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1877
William Lallemand82fe75c2012-10-23 10:25:10 +02001878 /* default compression options */
1879 if (defproxy.comp != NULL) {
1880 curproxy->comp = calloc(1, sizeof(struct comp));
1881 curproxy->comp->algos = defproxy.comp->algos;
1882 curproxy->comp->types = defproxy.comp->types;
1883 }
1884
Willy Tarreaubaaee002006-06-26 02:48:02 +02001885 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001886 curproxy->conf.used_listener_id = EB_ROOT;
1887 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001888
Willy Tarreau93893792009-07-23 13:19:11 +02001889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 }
1891 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1892 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001893 /* FIXME-20070101: we should do this too at the end of the
1894 * config parsing to free all default values.
1895 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001896 free(defproxy.check_req);
1897 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001898 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001899 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001900 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001901 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001902 free(defproxy.capture_name);
1903 free(defproxy.monitor_uri);
1904 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001905 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001906 free(defproxy.fwdfor_hdr_name);
1907 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001908 free(defproxy.orgto_hdr_name);
1909 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001910 free(defproxy.server_id_hdr_name);
1911 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001912 free(defproxy.expect_str);
1913 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001914
Willy Tarreau39b06652012-06-01 10:58:06 +02001915 if (defproxy.logformat_string != default_http_log_format &&
1916 defproxy.logformat_string != default_tcp_log_format &&
1917 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001918 free(defproxy.logformat_string);
1919
1920 free(defproxy.uniqueid_format_string);
1921
Willy Tarreaua534fea2008-08-03 12:19:50 +02001922 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001923 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001924
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 /* we cannot free uri_auth because it might already be used */
1926 init_default_instance();
1927 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001928 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 }
1931 else if (curproxy == NULL) {
1932 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 }
1936
Willy Tarreau977b8e42006-12-29 14:19:17 +01001937
1938 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001940 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001941 int cur_arg;
1942
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 if (curproxy == &defproxy) {
1944 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001945 err_code |= ERR_ALERT | ERR_FATAL;
1946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001948 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001949 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950
Willy Tarreau24709282013-03-10 21:32:12 +01001951 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001952 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001953 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_ALERT | ERR_FATAL;
1955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001957
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001958 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001959
1960 /* use default settings for unix sockets */
1961 bind_conf->ux.uid = global.unix_bind.ux.uid;
1962 bind_conf->ux.gid = global.unix_bind.ux.gid;
1963 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001964
1965 /* NOTE: the following line might create several listeners if there
1966 * are comma-separated IPs or port ranges. So all further processing
1967 * will have to be applied to all listeners created after last_listen.
1968 */
Willy Tarreau902636f2013-03-10 19:44:48 +01001969 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
1970 if (errmsg && *errmsg) {
1971 indent_msg(&errmsg, 2);
1972 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001973 }
1974 else
1975 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1976 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001977 err_code |= ERR_ALERT | ERR_FATAL;
1978 goto out;
1979 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001980
Willy Tarreau4348fad2012-09-20 16:48:07 +02001981 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1982 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001983 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001984 }
1985
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001986 cur_arg = 2;
1987 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001988 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001989 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001990 char *err;
1991
Willy Tarreau26982662012-09-12 23:17:10 +02001992 kw = bind_find_kw(args[cur_arg]);
1993 if (kw) {
1994 char *err = NULL;
1995 int code;
1996
1997 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001998 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1999 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002000 cur_arg += 1 + kw->skip ;
2001 err_code |= ERR_ALERT | ERR_FATAL;
2002 goto out;
2003 }
2004
Willy Tarreau4348fad2012-09-20 16:48:07 +02002005 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002006 err_code |= code;
2007
2008 if (code) {
2009 if (err && *err) {
2010 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002011 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002012 }
2013 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002014 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2015 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002016 if (code & ERR_FATAL) {
2017 free(err);
2018 cur_arg += 1 + kw->skip;
2019 goto out;
2020 }
2021 }
2022 free(err);
2023 cur_arg += 1 + kw->skip;
2024 continue;
2025 }
2026
Willy Tarreau8638f482012-09-18 18:01:17 +02002027 err = NULL;
2028 if (!bind_dumped) {
2029 bind_dump_kws(&err);
2030 indent_msg(&err, 4);
2031 bind_dumped = 1;
2032 }
2033
2034 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2035 file, linenum, args[0], args[1], args[cur_arg],
2036 err ? " Registered keywords :" : "", err ? err : "");
2037 free(err);
2038
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002041 }
Willy Tarreau93893792009-07-23 13:19:11 +02002042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043 }
2044 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2045 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2046 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002051 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002052 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002053
Willy Tarreaubaaee002006-06-26 02:48:02 +02002054 /* flush useless bits */
2055 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002057 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002058 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002059 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002060 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002061
Willy Tarreau1c47f852006-07-09 08:22:27 +02002062 if (!*args[1]) {
2063 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002067 }
2068
Willy Tarreaua534fea2008-08-03 12:19:50 +02002069 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002070 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002071 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002072 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002073 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2074
Willy Tarreau93893792009-07-23 13:19:11 +02002075 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2078 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2079 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2080 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2081 else {
2082 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 }
2086 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002087 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002088 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002089
2090 if (curproxy == &defproxy) {
2091 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2092 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002095 }
2096
2097 if (!*args[1]) {
2098 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2099 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002102 }
2103
2104 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002105 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002106
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002107 if (curproxy->uuid <= 0) {
2108 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002109 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
2111 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002112 }
2113
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002114 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2115 if (node) {
2116 struct proxy *target = container_of(node, struct proxy, conf.id);
2117 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2118 file, linenum, proxy_type_str(curproxy), curproxy->id,
2119 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
2122 }
2123 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002124 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002125 else if (!strcmp(args[0], "description")) {
2126 int i, len=0;
2127 char *d;
2128
Cyril Bonté99ed3272010-01-24 23:29:44 +01002129 if (curproxy == &defproxy) {
2130 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2131 file, linenum, args[0]);
2132 err_code |= ERR_ALERT | ERR_FATAL;
2133 goto out;
2134 }
2135
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002136 if (!*args[1]) {
2137 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2138 file, linenum, args[0]);
2139 return -1;
2140 }
2141
2142 for(i=1; *args[i]; i++)
2143 len += strlen(args[i])+1;
2144
2145 d = (char *)calloc(1, len);
2146 curproxy->desc = d;
2147
2148 d += sprintf(d, "%s", args[1]);
2149 for(i=2; *args[i]; i++)
2150 d += sprintf(d, " %s", args[i]);
2151
2152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002153 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2154 curproxy->state = PR_STSTOPPED;
2155 }
2156 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2157 curproxy->state = PR_STNEW;
2158 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002159 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2160 int cur_arg = 1;
2161 unsigned int set = 0;
2162
2163 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002164 unsigned int low, high;
2165
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002166 if (strcmp(args[cur_arg], "all") == 0) {
2167 set = 0;
2168 break;
2169 }
2170 else if (strcmp(args[cur_arg], "odd") == 0) {
2171 set |= 0x55555555;
2172 }
2173 else if (strcmp(args[cur_arg], "even") == 0) {
2174 set |= 0xAAAAAAAA;
2175 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002176 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002177 char *dash = strchr(args[cur_arg], '-');
2178
2179 low = high = str2uic(args[cur_arg]);
2180 if (dash)
2181 high = str2uic(dash + 1);
2182
2183 if (high < low) {
2184 unsigned int swap = low;
2185 low = high;
2186 high = swap;
2187 }
2188
2189 if (low < 1 || high > 32) {
2190 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002191 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002194 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002195
2196 if (high > global.nbproc) {
2197 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2198 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002200 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002201 while (low <= high)
2202 set |= 1 << (low++ - 1);
2203 }
2204 else {
2205 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2206 file, linenum, args[0]);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002209 }
2210 cur_arg++;
2211 }
2212 curproxy->bind_proc = set;
2213 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002214 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002215 if (curproxy == &defproxy) {
2216 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002217 err_code |= ERR_ALERT | ERR_FATAL;
2218 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002219 }
2220
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002221 err = invalid_char(args[1]);
2222 if (err) {
2223 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2224 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002225 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002226 }
2227
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002228 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2229 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2230 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002233 }
2234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2236 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237
Willy Tarreau977b8e42006-12-29 14:19:17 +01002238 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002239 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002240
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 if (*(args[1]) == 0) {
2242 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2243 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002246 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002247
Willy Tarreau67402132012-05-31 20:40:20 +02002248 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002249 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002250 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002251 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 curproxy->cookie_name = strdup(args[1]);
2253 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002254
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 cur_arg = 2;
2256 while (*(args[cur_arg])) {
2257 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002258 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 }
2260 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002261 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 }
2263 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002264 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 }
2266 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002267 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 }
2269 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002270 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002272 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002273 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002276 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002278 else if (!strcmp(args[cur_arg], "httponly")) {
2279 curproxy->ck_opts |= PR_CK_HTTPONLY;
2280 }
2281 else if (!strcmp(args[cur_arg], "secure")) {
2282 curproxy->ck_opts |= PR_CK_SECURE;
2283 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002284 else if (!strcmp(args[cur_arg], "domain")) {
2285 if (!*args[cur_arg + 1]) {
2286 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2287 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002290 }
2291
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002292 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002293 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002294 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2295 " dots nor does not start with a dot."
2296 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002297 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002298 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002299 }
2300
2301 err = invalid_domainchar(args[cur_arg + 1]);
2302 if (err) {
2303 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2304 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002307 }
2308
Willy Tarreau68a897b2009-12-03 23:28:34 +01002309 if (!curproxy->cookie_domain) {
2310 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2311 } else {
2312 /* one domain was already specified, add another one by
2313 * building the string which will be returned along with
2314 * the cookie.
2315 */
2316 char *new_ptr;
2317 int new_len = strlen(curproxy->cookie_domain) +
2318 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2319 new_ptr = malloc(new_len);
2320 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2321 free(curproxy->cookie_domain);
2322 curproxy->cookie_domain = new_ptr;
2323 }
Willy Tarreau31936852010-10-06 16:59:56 +02002324 cur_arg++;
2325 }
2326 else if (!strcmp(args[cur_arg], "maxidle")) {
2327 unsigned int maxidle;
2328 const char *res;
2329
2330 if (!*args[cur_arg + 1]) {
2331 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2332 file, linenum, args[cur_arg]);
2333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
2335 }
2336
2337 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2338 if (res) {
2339 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2340 file, linenum, *res, args[cur_arg]);
2341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
2343 }
2344 curproxy->cookie_maxidle = maxidle;
2345 cur_arg++;
2346 }
2347 else if (!strcmp(args[cur_arg], "maxlife")) {
2348 unsigned int maxlife;
2349 const char *res;
2350
2351 if (!*args[cur_arg + 1]) {
2352 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2353 file, linenum, args[cur_arg]);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357
2358 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2359 if (res) {
2360 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2361 file, linenum, *res, args[cur_arg]);
2362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
2365 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002366 cur_arg++;
2367 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002369 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 +02002370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
2374 cur_arg++;
2375 }
Willy Tarreau67402132012-05-31 20:40:20 +02002376 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2378 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002379 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
2381
Willy Tarreau67402132012-05-31 20:40:20 +02002382 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2384 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002385 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002387
Willy Tarreau67402132012-05-31 20:40:20 +02002388 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002389 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2390 file, linenum);
2391 err_code |= ERR_ALERT | ERR_FATAL;
2392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002394 else if (!strcmp(args[0], "persist")) { /* persist */
2395 if (*(args[1]) == 0) {
2396 Alert("parsing [%s:%d] : missing persist method.\n",
2397 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002400 }
2401
2402 if (!strncmp(args[1], "rdp-cookie", 10)) {
2403 curproxy->options2 |= PR_O2_RDPC_PRST;
2404
Emeric Brunb982a3d2010-01-04 15:45:53 +01002405 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002406 const char *beg, *end;
2407
2408 beg = args[1] + 11;
2409 end = strchr(beg, ')');
2410
2411 if (!end || end == beg) {
2412 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2413 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002416 }
2417
2418 free(curproxy->rdp_cookie_name);
2419 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2420 curproxy->rdp_cookie_len = end-beg;
2421 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002422 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002423 free(curproxy->rdp_cookie_name);
2424 curproxy->rdp_cookie_name = strdup("msts");
2425 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2426 }
2427 else { /* syntax */
2428 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2429 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002432 }
2433 }
2434 else {
2435 Alert("parsing [%s:%d] : unknown persist method.\n",
2436 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002439 }
2440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002442 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002444 if (curproxy == &defproxy) {
2445 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
2448 }
2449
Willy Tarreau977b8e42006-12-29 14:19:17 +01002450 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002452
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002454 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 }
2459 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002460 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 curproxy->appsession_name = strdup(args[1]);
2462 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2463 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002464 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2465 if (err) {
2466 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2467 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002470 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002471 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002472
Willy Tarreau51041c72007-09-09 21:56:53 +02002473 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2474 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_ABORT;
2476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002478
2479 cur_arg = 6;
2480 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002481 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2482 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002483 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002484 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002485 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002486 } else if (!strcmp(args[cur_arg], "prefix")) {
2487 curproxy->options2 |= PR_O2_AS_PFX;
2488 } else if (!strcmp(args[cur_arg], "mode")) {
2489 if (!*args[cur_arg + 1]) {
2490 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2491 file, linenum, args[0], args[cur_arg]);
2492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
2494 }
2495
2496 cur_arg++;
2497 if (!strcmp(args[cur_arg], "query-string")) {
2498 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2499 curproxy->options2 |= PR_O2_AS_M_QS;
2500 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2501 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2502 curproxy->options2 |= PR_O2_AS_M_PP;
2503 } else {
2504 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
2507 }
2508 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002509 cur_arg++;
2510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 } /* Url App Session */
2512 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002513 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002515
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002517 if (curproxy == &defproxy) {
2518 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
2521 }
2522
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 if (*(args[4]) == 0) {
2524 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2525 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002529 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530 curproxy->capture_name = strdup(args[2]);
2531 curproxy->capture_namelen = strlen(curproxy->capture_name);
2532 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 curproxy->to_log |= LW_COOKIE;
2534 }
2535 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2536 struct cap_hdr *hdr;
2537
2538 if (curproxy == &defproxy) {
2539 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 }
2543
2544 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2545 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2546 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 }
2550
2551 hdr = calloc(sizeof(struct cap_hdr), 1);
2552 hdr->next = curproxy->req_cap;
2553 hdr->name = strdup(args[3]);
2554 hdr->namelen = strlen(args[3]);
2555 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002556 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 hdr->index = curproxy->nb_req_cap++;
2558 curproxy->req_cap = hdr;
2559 curproxy->to_log |= LW_REQHDR;
2560 }
2561 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2562 struct cap_hdr *hdr;
2563
2564 if (curproxy == &defproxy) {
2565 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 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 }
2569
2570 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2571 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2572 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
2576 hdr = calloc(sizeof(struct cap_hdr), 1);
2577 hdr->next = curproxy->rsp_cap;
2578 hdr->name = strdup(args[3]);
2579 hdr->namelen = strlen(args[3]);
2580 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002581 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 hdr->index = curproxy->nb_rsp_cap++;
2583 curproxy->rsp_cap = hdr;
2584 curproxy->to_log |= LW_RSPHDR;
2585 }
2586 else {
2587 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2588 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002589 err_code |= ERR_ALERT | ERR_FATAL;
2590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 }
2592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002594 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002595 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002596
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 if (*(args[1]) == 0) {
2598 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2599 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 }
2603 curproxy->conn_retries = atol(args[1]);
2604 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002605 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002606 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002607
2608 if (curproxy == &defproxy) {
2609 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
2612 }
2613
Willy Tarreau20b0de52012-12-24 15:45:22 +01002614 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2615 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2616 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2617 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2618 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2619 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 +01002620 file, linenum, args[0]);
2621 err_code |= ERR_WARN;
2622 }
2623
Willy Tarreauff011f22011-01-06 17:51:27 +01002624 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002625
Willy Tarreauff011f22011-01-06 17:51:27 +01002626 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002627 err_code |= ERR_ALERT | ERR_ABORT;
2628 goto out;
2629 }
2630
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002631 err_code |= warnif_cond_conflicts(rule->cond,
2632 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2633 file, linenum);
2634
Willy Tarreauff011f22011-01-06 17:51:27 +01002635 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002636 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002637 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2638 /* set the header name and length into the proxy structure */
2639 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2640 err_code |= ERR_WARN;
2641
2642 if (!*args[1]) {
2643 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2644 file, linenum, args[0]);
2645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
2647 }
2648
2649 /* set the desired header name */
2650 free(curproxy->server_id_hdr_name);
2651 curproxy->server_id_hdr_name = strdup(args[1]);
2652 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2653 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002654 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002655 if (curproxy == &defproxy) {
2656 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002659 }
2660
Willy Tarreauef6494c2010-01-28 17:12:36 +01002661 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002662 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2663 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002666 }
2667
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002668 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2669 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2670 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002673 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002674
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002675 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002676 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002677 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002678 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002679 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002680
Cyril Bonté99ed3272010-01-24 23:29:44 +01002681 if (curproxy == &defproxy) {
2682 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
2685 }
2686
Willy Tarreau4baae242012-12-27 12:00:31 +01002687 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2688 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2689 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002692 }
2693
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002694 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002695 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002696 err_code |= warnif_cond_conflicts(rule->cond,
2697 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2698 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002699 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002700 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002701 struct switching_rule *rule;
2702
Willy Tarreaub099aca2008-10-12 17:26:37 +02002703 if (curproxy == &defproxy) {
2704 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002707 }
2708
Willy Tarreau55ea7572007-06-17 19:56:27 +02002709 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002711
2712 if (*(args[1]) == 0) {
2713 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002716 }
2717
Willy Tarreauef6494c2010-01-28 17:12:36 +01002718 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002719 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2720 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002723 }
2724
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002725 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2726 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2727 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002730 }
2731
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002732 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002733
Willy Tarreau55ea7572007-06-17 19:56:27 +02002734 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2735 rule->cond = cond;
2736 rule->be.name = strdup(args[1]);
2737 LIST_INIT(&rule->list);
2738 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2739 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002740 else if (strcmp(args[0], "use-server") == 0) {
2741 struct server_rule *rule;
2742
2743 if (curproxy == &defproxy) {
2744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748
2749 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2750 err_code |= ERR_WARN;
2751
2752 if (*(args[1]) == 0) {
2753 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
2756 }
2757
2758 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2759 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2760 file, linenum, args[0]);
2761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
2763 }
2764
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002765 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2766 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2767 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
2770 }
2771
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002772 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002773
2774 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2775 rule->cond = cond;
2776 rule->srv.name = strdup(args[1]);
2777 LIST_INIT(&rule->list);
2778 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2779 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2780 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002781 else if ((!strcmp(args[0], "force-persist")) ||
2782 (!strcmp(args[0], "ignore-persist"))) {
2783 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002784
2785 if (curproxy == &defproxy) {
2786 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2787 err_code |= ERR_ALERT | ERR_FATAL;
2788 goto out;
2789 }
2790
2791 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2792 err_code |= ERR_WARN;
2793
Willy Tarreauef6494c2010-01-28 17:12:36 +01002794 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002795 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2796 file, linenum, args[0]);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
2799 }
2800
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002801 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2802 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2803 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
2807
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002808 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2809 * where force-persist is applied.
2810 */
2811 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002812
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002813 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002814 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002815 if (!strcmp(args[0], "force-persist")) {
2816 rule->type = PERSIST_TYPE_FORCE;
2817 } else {
2818 rule->type = PERSIST_TYPE_IGNORE;
2819 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002820 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002821 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002822 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002823 else if (!strcmp(args[0], "stick-table")) {
2824 int myidx = 1;
2825
Emeric Brun32da3c42010-09-23 18:39:19 +02002826 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002827 curproxy->table.type = (unsigned int)-1;
2828 while (*args[myidx]) {
2829 const char *err;
2830
2831 if (strcmp(args[myidx], "size") == 0) {
2832 myidx++;
2833 if (!*(args[myidx])) {
2834 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2835 file, linenum, args[myidx-1]);
2836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
2838 }
2839 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2840 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2841 file, linenum, *err, args[myidx-1]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
2844 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002845 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002846 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002847 else if (strcmp(args[myidx], "peers") == 0) {
2848 myidx++;
2849 if (!*(args[myidx])) {
2850 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2851 file, linenum, args[myidx-1]);
2852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
2854 }
2855 curproxy->table.peers.name = strdup(args[myidx++]);
2856 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002857 else if (strcmp(args[myidx], "expire") == 0) {
2858 myidx++;
2859 if (!*(args[myidx])) {
2860 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2861 file, linenum, args[myidx-1]);
2862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
2864 }
2865 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2866 if (err) {
2867 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2868 file, linenum, *err, args[myidx-1]);
2869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002873 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002874 }
2875 else if (strcmp(args[myidx], "nopurge") == 0) {
2876 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002877 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002878 }
2879 else if (strcmp(args[myidx], "type") == 0) {
2880 myidx++;
2881 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2882 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2883 file, linenum, args[myidx]);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002887 /* myidx already points to next arg */
2888 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002889 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002890 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002891 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002892
2893 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002894 nw = args[myidx];
2895 while (*nw) {
2896 /* the "store" keyword supports a comma-separated list */
2897 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002898 sa = NULL; /* store arg */
2899 while (*nw && *nw != ',') {
2900 if (*nw == '(') {
2901 *nw = 0;
2902 sa = ++nw;
2903 while (*nw != ')') {
2904 if (!*nw) {
2905 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2906 file, linenum, args[0], cw);
2907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
2909 }
2910 nw++;
2911 }
2912 *nw = '\0';
2913 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002914 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002915 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002916 if (*nw)
2917 *nw++ = '\0';
2918 type = stktable_get_data_type(cw);
2919 if (type < 0) {
2920 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2921 file, linenum, args[0], cw);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
Willy Tarreauac782882010-06-20 10:41:54 +02002925
2926 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2927 switch (err) {
2928 case PE_NONE: break;
2929 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002930 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2931 file, linenum, args[0], cw);
2932 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002933 break;
2934
2935 case PE_ARG_MISSING:
2936 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2937 file, linenum, args[0], cw);
2938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
2940
2941 case PE_ARG_NOT_USED:
2942 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2943 file, linenum, args[0], cw);
2944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
2946
2947 default:
2948 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2949 file, linenum, args[0], cw);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002952 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002953 }
2954 myidx++;
2955 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002956 else {
2957 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2958 file, linenum, args[myidx]);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002961 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002962 }
2963
2964 if (!curproxy->table.size) {
2965 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2966 file, linenum);
2967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
2969 }
2970
2971 if (curproxy->table.type == (unsigned int)-1) {
2972 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2973 file, linenum);
2974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
2976 }
2977 }
2978 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002979 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002980 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002981 int myidx = 0;
2982 const char *name = NULL;
2983 int flags;
2984
2985 if (curproxy == &defproxy) {
2986 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990
2991 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2992 err_code |= ERR_WARN;
2993 goto out;
2994 }
2995
2996 myidx++;
2997 if ((strcmp(args[myidx], "store") == 0) ||
2998 (strcmp(args[myidx], "store-request") == 0)) {
2999 myidx++;
3000 flags = STK_IS_STORE;
3001 }
3002 else if (strcmp(args[myidx], "store-response") == 0) {
3003 myidx++;
3004 flags = STK_IS_STORE | STK_ON_RSP;
3005 }
3006 else if (strcmp(args[myidx], "match") == 0) {
3007 myidx++;
3008 flags = STK_IS_MATCH;
3009 }
3010 else if (strcmp(args[myidx], "on") == 0) {
3011 myidx++;
3012 flags = STK_IS_MATCH | STK_IS_STORE;
3013 }
3014 else {
3015 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3016 err_code |= ERR_ALERT | ERR_FATAL;
3017 goto out;
3018 }
3019
3020 if (*(args[myidx]) == 0) {
3021 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003026 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003028 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
3031 }
3032
3033 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003034 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3035 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3036 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003037 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003038 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003039 goto out;
3040 }
3041 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003042 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3043 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3044 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003046 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 goto out;
3048 }
3049 }
3050
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003051 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003052 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003053
Emeric Brunb982a3d2010-01-04 15:45:53 +01003054 if (strcmp(args[myidx], "table") == 0) {
3055 myidx++;
3056 name = args[myidx++];
3057 }
3058
Willy Tarreauef6494c2010-01-28 17:12:36 +01003059 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003060 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3061 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3062 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003063 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003064 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003065 goto out;
3066 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003067 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003068 else if (*(args[myidx])) {
3069 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3070 file, linenum, args[0], args[myidx]);
3071 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003072 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003073 goto out;
3074 }
Emeric Brun97679e72010-09-23 17:56:44 +02003075 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003076 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003077 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003078 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003079
Emeric Brunb982a3d2010-01-04 15:45:53 +01003080 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3081 rule->cond = cond;
3082 rule->expr = expr;
3083 rule->flags = flags;
3084 rule->table.name = name ? strdup(name) : NULL;
3085 LIST_INIT(&rule->list);
3086 if (flags & STK_ON_RSP)
3087 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3088 else
3089 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003092 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003094
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3096 curproxy->uri_auth = NULL; /* we must detach from the default config */
3097
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003098 if (!*args[1]) {
3099 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003100 } else if (!strcmp(args[1], "admin")) {
3101 struct stats_admin_rule *rule;
3102
3103 if (curproxy == &defproxy) {
3104 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
3107 }
3108
3109 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3110 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3111 err_code |= ERR_ALERT | ERR_ABORT;
3112 goto out;
3113 }
3114
3115 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3116 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3117 file, linenum, args[0], args[1]);
3118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
3120 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003121 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3122 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3123 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
3127
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003128 err_code |= warnif_cond_conflicts(cond,
3129 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3130 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003131
3132 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3133 rule->cond = cond;
3134 LIST_INIT(&rule->list);
3135 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 } else if (!strcmp(args[1], "uri")) {
3137 if (*(args[2]) == 0) {
3138 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3142 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_ABORT;
3144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
3146 } else if (!strcmp(args[1], "realm")) {
3147 if (*(args[2]) == 0) {
3148 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3152 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_ABORT;
3154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003156 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003157 unsigned interval;
3158
3159 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3160 if (err) {
3161 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3162 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003165 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3166 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_ALERT | ERR_ABORT;
3168 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003169 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003170 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003171 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003172
3173 if (curproxy == &defproxy) {
3174 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
3177 }
3178
3179 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3180 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3181 err_code |= ERR_ALERT | ERR_ABORT;
3182 goto out;
3183 }
3184
Willy Tarreauff011f22011-01-06 17:51:27 +01003185 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3186 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003187 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3188 file, linenum, args[0]);
3189 err_code |= ERR_WARN;
3190 }
3191
Willy Tarreauff011f22011-01-06 17:51:27 +01003192 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003193
Willy Tarreauff011f22011-01-06 17:51:27 +01003194 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003195 err_code |= ERR_ALERT | ERR_ABORT;
3196 goto out;
3197 }
3198
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003199 err_code |= warnif_cond_conflicts(rule->cond,
3200 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3201 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003202 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003203
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 } else if (!strcmp(args[1], "auth")) {
3205 if (*(args[2]) == 0) {
3206 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3210 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_ABORT;
3212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 }
3214 } else if (!strcmp(args[1], "scope")) {
3215 if (*(args[2]) == 0) {
3216 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3220 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_ABORT;
3222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 }
3224 } else if (!strcmp(args[1], "enable")) {
3225 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3226 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_ABORT;
3228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003230 } else if (!strcmp(args[1], "hide-version")) {
3231 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3232 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_ABORT;
3234 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003235 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003236 } else if (!strcmp(args[1], "show-legends")) {
3237 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3238 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3239 err_code |= ERR_ALERT | ERR_ABORT;
3240 goto out;
3241 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003242 } else if (!strcmp(args[1], "show-node")) {
3243
3244 if (*args[2]) {
3245 int i;
3246 char c;
3247
3248 for (i=0; args[2][i]; i++) {
3249 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003250 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3251 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003252 break;
3253 }
3254
3255 if (!i || args[2][i]) {
3256 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3257 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3258 file, linenum, args[0], args[1]);
3259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
3261 }
3262 }
3263
3264 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3265 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3266 err_code |= ERR_ALERT | ERR_ABORT;
3267 goto out;
3268 }
3269 } else if (!strcmp(args[1], "show-desc")) {
3270 char *desc = NULL;
3271
3272 if (*args[2]) {
3273 int i, len=0;
3274 char *d;
3275
3276 for(i=2; *args[i]; i++)
3277 len += strlen(args[i])+1;
3278
3279 desc = d = (char *)calloc(1, len);
3280
3281 d += sprintf(d, "%s", args[2]);
3282 for(i=3; *args[i]; i++)
3283 d += sprintf(d, " %s", args[i]);
3284 }
3285
3286 if (!*args[2] && !global.desc)
3287 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3288 file, linenum, args[1]);
3289 else {
3290 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3291 free(desc);
3292 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3293 err_code |= ERR_ALERT | ERR_ABORT;
3294 goto out;
3295 }
3296 free(desc);
3297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003299stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003300 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 +01003301 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003302 err_code |= ERR_ALERT | ERR_FATAL;
3303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
3305 }
3306 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307 int optnum;
3308
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003309 if (*(args[1]) == '\0') {
3310 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3311 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003315
3316 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3317 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003318 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3319 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3320 file, linenum, cfg_opts[optnum].name);
3321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
3323 }
Willy Tarreau93893792009-07-23 13:19:11 +02003324 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3325 err_code |= ERR_WARN;
3326 goto out;
3327 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003328
Willy Tarreau3842f002009-06-14 11:39:52 +02003329 curproxy->no_options &= ~cfg_opts[optnum].val;
3330 curproxy->options &= ~cfg_opts[optnum].val;
3331
3332 switch (kwm) {
3333 case KWM_STD:
3334 curproxy->options |= cfg_opts[optnum].val;
3335 break;
3336 case KWM_NO:
3337 curproxy->no_options |= cfg_opts[optnum].val;
3338 break;
3339 case KWM_DEF: /* already cleared */
3340 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003341 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003342
Willy Tarreau93893792009-07-23 13:19:11 +02003343 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003344 }
3345 }
3346
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003347 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3348 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003349 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3350 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3351 file, linenum, cfg_opts2[optnum].name);
3352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
3354 }
Willy Tarreau93893792009-07-23 13:19:11 +02003355 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3356 err_code |= ERR_WARN;
3357 goto out;
3358 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003359
Willy Tarreau3842f002009-06-14 11:39:52 +02003360 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3361 curproxy->options2 &= ~cfg_opts2[optnum].val;
3362
3363 switch (kwm) {
3364 case KWM_STD:
3365 curproxy->options2 |= cfg_opts2[optnum].val;
3366 break;
3367 case KWM_NO:
3368 curproxy->no_options2 |= cfg_opts2[optnum].val;
3369 break;
3370 case KWM_DEF: /* already cleared */
3371 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003372 }
Willy Tarreau93893792009-07-23 13:19:11 +02003373 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003374 }
3375 }
3376
Willy Tarreau3842f002009-06-14 11:39:52 +02003377 if (kwm != KWM_STD) {
3378 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003379 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003382 }
3383
Emeric Brun3a058f32009-06-30 18:26:00 +02003384 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003385 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003387 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003388 if (*(args[2]) != '\0') {
3389 if (!strcmp(args[2], "clf")) {
3390 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003391 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003392 } else {
3393 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003394 err_code |= ERR_ALERT | ERR_FATAL;
3395 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003396 }
3397 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003398 if (curproxy->logformat_string != default_http_log_format &&
3399 curproxy->logformat_string != default_tcp_log_format &&
3400 curproxy->logformat_string != clf_http_log_format)
3401 free(curproxy->logformat_string);
3402 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003403 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003404 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003406 if (curproxy->logformat_string != default_http_log_format &&
3407 curproxy->logformat_string != default_tcp_log_format &&
3408 curproxy->logformat_string != clf_http_log_format)
3409 free(curproxy->logformat_string);
3410 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003411 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 else if (!strcmp(args[1], "tcpka")) {
3413 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003414 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003416
3417 if (curproxy->cap & PR_CAP_FE)
3418 curproxy->options |= PR_O_TCP_CLI_KA;
3419 if (curproxy->cap & PR_CAP_BE)
3420 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 }
3422 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003424 err_code |= ERR_WARN;
3425
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003427 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003428 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003429 curproxy->options2 &= ~PR_O2_CHK_ANY;
3430 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 if (!*args[2]) { /* no argument */
3432 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3433 curproxy->check_len = strlen(DEF_CHECK_REQ);
3434 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003435 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 curproxy->check_req = (char *)malloc(reqlen);
3437 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003438 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003440 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 if (*args[4])
3442 reqlen += strlen(args[4]);
3443 else
3444 reqlen += strlen("HTTP/1.0");
3445
3446 curproxy->check_req = (char *)malloc(reqlen);
3447 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003448 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003449 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003450 }
3451 else if (!strcmp(args[1], "ssl-hello-chk")) {
3452 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003453 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003454 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003455
Willy Tarreaua534fea2008-08-03 12:19:50 +02003456 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003457 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003458 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003459 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003460 }
Willy Tarreau23677902007-05-08 23:50:35 +02003461 else if (!strcmp(args[1], "smtpchk")) {
3462 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003463 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003464 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003465 curproxy->options2 &= ~PR_O2_CHK_ANY;
3466 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003467
3468 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3469 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3470 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3471 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3472 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3473 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3474 curproxy->check_req = (char *)malloc(reqlen);
3475 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3476 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3477 } else {
3478 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3479 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3480 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3481 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3482 }
3483 }
3484 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003485 else if (!strcmp(args[1], "lb-agent-chk")) {
3486 /* use dynmaic health check */
3487 free(curproxy->check_req);
3488 curproxy->check_req = NULL;
3489 curproxy->options2 &= ~PR_O2_CHK_ANY;
3490 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3491 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003492 else if (!strcmp(args[1], "pgsql-check")) {
3493 /* use PostgreSQL request to check servers' health */
3494 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3495 err_code |= ERR_WARN;
3496
3497 free(curproxy->check_req);
3498 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003499 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003500 curproxy->options2 |= PR_O2_PGSQL_CHK;
3501
3502 if (*(args[2])) {
3503 int cur_arg = 2;
3504
3505 while (*(args[cur_arg])) {
3506 if (strcmp(args[cur_arg], "user") == 0) {
3507 char * packet;
3508 uint32_t packet_len;
3509 uint32_t pv;
3510
3511 /* suboption header - needs additional argument for it */
3512 if (*(args[cur_arg+1]) == 0) {
3513 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3514 file, linenum, args[0], args[1], args[cur_arg]);
3515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
3517 }
3518
3519 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3520 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3521 pv = htonl(0x30000); /* protocol version 3.0 */
3522
3523 packet = (char*) calloc(1, packet_len);
3524
3525 memcpy(packet + 4, &pv, 4);
3526
3527 /* copy "user" */
3528 memcpy(packet + 8, "user", 4);
3529
3530 /* copy username */
3531 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3532
3533 free(curproxy->check_req);
3534 curproxy->check_req = packet;
3535 curproxy->check_len = packet_len;
3536
3537 packet_len = htonl(packet_len);
3538 memcpy(packet, &packet_len, 4);
3539 cur_arg += 2;
3540 } else {
3541 /* unknown suboption - catchall */
3542 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3543 file, linenum, args[0], args[1]);
3544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
3546 }
3547 } /* end while loop */
3548 }
3549 }
3550
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003551 else if (!strcmp(args[1], "redis-check")) {
3552 /* use REDIS PING request to check servers' health */
3553 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3554 err_code |= ERR_WARN;
3555
3556 free(curproxy->check_req);
3557 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003558 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003559 curproxy->options2 |= PR_O2_REDIS_CHK;
3560
3561 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3562 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3563 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3564 }
3565
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003566 else if (!strcmp(args[1], "mysql-check")) {
3567 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003568 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3569 err_code |= ERR_WARN;
3570
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003571 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003572 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003573 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003574 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003575
3576 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3577 * const char mysql40_client_auth_pkt[] = {
3578 * "\x0e\x00\x00" // packet length
3579 * "\x01" // packet number
3580 * "\x00\x00" // client capabilities
3581 * "\x00\x00\x01" // max packet
3582 * "haproxy\x00" // username (null terminated string)
3583 * "\x00" // filler (always 0x00)
3584 * "\x01\x00\x00" // packet length
3585 * "\x00" // packet number
3586 * "\x01" // COM_QUIT command
3587 * };
3588 */
3589
3590 if (*(args[2])) {
3591 int cur_arg = 2;
3592
3593 while (*(args[cur_arg])) {
3594 if (strcmp(args[cur_arg], "user") == 0) {
3595 char *mysqluser;
3596 int packetlen, reqlen, userlen;
3597
3598 /* suboption header - needs additional argument for it */
3599 if (*(args[cur_arg+1]) == 0) {
3600 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3601 file, linenum, args[0], args[1], args[cur_arg]);
3602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
3604 }
3605 mysqluser = args[cur_arg + 1];
3606 userlen = strlen(mysqluser);
3607 packetlen = userlen + 7;
3608 reqlen = packetlen + 9;
3609
3610 free(curproxy->check_req);
3611 curproxy->check_req = (char *)calloc(1, reqlen);
3612 curproxy->check_len = reqlen;
3613
3614 snprintf(curproxy->check_req, 4, "%c%c%c",
3615 ((unsigned char) packetlen & 0xff),
3616 ((unsigned char) (packetlen >> 8) & 0xff),
3617 ((unsigned char) (packetlen >> 16) & 0xff));
3618
3619 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003620 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003621 curproxy->check_req[8] = 1;
3622 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3623 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3624 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3625 cur_arg += 2;
3626 } else {
3627 /* unknown suboption - catchall */
3628 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3629 file, linenum, args[0], args[1]);
3630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
3632 }
3633 } /* end while loop */
3634 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003635 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003636 else if (!strcmp(args[1], "ldap-check")) {
3637 /* use LDAP request to check servers' health */
3638 free(curproxy->check_req);
3639 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003640 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003641 curproxy->options2 |= PR_O2_LDAP_CHK;
3642
3643 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3644 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3645 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3646 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003647 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003648 int cur_arg;
3649
3650 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3651 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003652 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003653
Willy Tarreau87cf5142011-08-19 22:57:24 +02003654 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003655
3656 free(curproxy->fwdfor_hdr_name);
3657 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3658 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3659
3660 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3661 cur_arg = 2;
3662 while (*(args[cur_arg])) {
3663 if (!strcmp(args[cur_arg], "except")) {
3664 /* suboption except - needs additional argument for it */
3665 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3666 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3667 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003670 }
3671 /* flush useless bits */
3672 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003673 cur_arg += 2;
3674 } else if (!strcmp(args[cur_arg], "header")) {
3675 /* suboption header - needs additional argument for it */
3676 if (*(args[cur_arg+1]) == 0) {
3677 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3678 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003681 }
3682 free(curproxy->fwdfor_hdr_name);
3683 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3684 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3685 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003686 } else if (!strcmp(args[cur_arg], "if-none")) {
3687 curproxy->options &= ~PR_O_FF_ALWAYS;
3688 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003689 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003690 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003691 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003692 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003693 err_code |= ERR_ALERT | ERR_FATAL;
3694 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003695 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003696 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003697 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003698 else if (!strcmp(args[1], "originalto")) {
3699 int cur_arg;
3700
3701 /* insert x-original-to field, but not for the IP address listed as an except.
3702 * set default options (ie: bitfield, header name, etc)
3703 */
3704
3705 curproxy->options |= PR_O_ORGTO;
3706
3707 free(curproxy->orgto_hdr_name);
3708 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3709 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3710
Willy Tarreau87cf5142011-08-19 22:57:24 +02003711 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003712 cur_arg = 2;
3713 while (*(args[cur_arg])) {
3714 if (!strcmp(args[cur_arg], "except")) {
3715 /* suboption except - needs additional argument for it */
3716 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3717 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3718 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003721 }
3722 /* flush useless bits */
3723 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3724 cur_arg += 2;
3725 } else if (!strcmp(args[cur_arg], "header")) {
3726 /* suboption header - needs additional argument for it */
3727 if (*(args[cur_arg+1]) == 0) {
3728 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3729 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003732 }
3733 free(curproxy->orgto_hdr_name);
3734 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3735 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3736 cur_arg += 2;
3737 } else {
3738 /* unknown suboption - catchall */
3739 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3740 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003743 }
3744 } /* end while loop */
3745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 else {
3747 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 }
Willy Tarreau93893792009-07-23 13:19:11 +02003751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003753 else if (!strcmp(args[0], "default_backend")) {
3754 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003756
3757 if (*(args[1]) == 0) {
3758 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003761 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003762 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003763 curproxy->defbe.name = strdup(args[1]);
3764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003766 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003768
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003769 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3770 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 /* enable reconnections to dispatch */
3773 curproxy->options |= PR_O_REDISP;
3774 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003775 else if (!strcmp(args[0], "http-check")) {
3776 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003778
3779 if (strcmp(args[1], "disable-on-404") == 0) {
3780 /* enable a graceful server shutdown on an HTTP 404 response */
3781 curproxy->options |= PR_O_DISABLE404;
3782 }
Willy Tarreauef781042010-01-27 11:53:01 +01003783 else if (strcmp(args[1], "send-state") == 0) {
3784 /* enable emission of the apparent state of a server in HTTP checks */
3785 curproxy->options2 |= PR_O2_CHK_SNDST;
3786 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003787 else if (strcmp(args[1], "expect") == 0) {
3788 const char *ptr_arg;
3789 int cur_arg;
3790
3791 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3792 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
3796
3797 cur_arg = 2;
3798 /* consider exclamation marks, sole or at the beginning of a word */
3799 while (*(ptr_arg = args[cur_arg])) {
3800 while (*ptr_arg == '!') {
3801 curproxy->options2 ^= PR_O2_EXP_INV;
3802 ptr_arg++;
3803 }
3804 if (*ptr_arg)
3805 break;
3806 cur_arg++;
3807 }
3808 /* now ptr_arg points to the beginning of a word past any possible
3809 * exclamation mark, and cur_arg is the argument which holds this word.
3810 */
3811 if (strcmp(ptr_arg, "status") == 0) {
3812 if (!*(args[cur_arg + 1])) {
3813 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3814 file, linenum, args[0], args[1], ptr_arg);
3815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
3817 }
3818 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003819 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003820 curproxy->expect_str = strdup(args[cur_arg + 1]);
3821 }
3822 else if (strcmp(ptr_arg, "string") == 0) {
3823 if (!*(args[cur_arg + 1])) {
3824 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3825 file, linenum, args[0], args[1], ptr_arg);
3826 err_code |= ERR_ALERT | ERR_FATAL;
3827 goto out;
3828 }
3829 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003830 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003831 curproxy->expect_str = strdup(args[cur_arg + 1]);
3832 }
3833 else if (strcmp(ptr_arg, "rstatus") == 0) {
3834 if (!*(args[cur_arg + 1])) {
3835 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3836 file, linenum, args[0], args[1], ptr_arg);
3837 err_code |= ERR_ALERT | ERR_FATAL;
3838 goto out;
3839 }
3840 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003841 free(curproxy->expect_str);
3842 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3843 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003844 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3845 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3846 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3847 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
3850 }
3851 }
3852 else if (strcmp(ptr_arg, "rstring") == 0) {
3853 if (!*(args[cur_arg + 1])) {
3854 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3855 file, linenum, args[0], args[1], ptr_arg);
3856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
3858 }
3859 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003860 free(curproxy->expect_str);
3861 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3862 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003863 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3864 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3865 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3866 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
3869 }
3870 }
3871 else {
3872 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3873 file, linenum, args[0], args[1], ptr_arg);
3874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
3876 }
3877 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003878 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003879 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 +02003880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003882 }
3883 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003884 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003885 if (curproxy == &defproxy) {
3886 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003889 }
3890
Willy Tarreaub80c2302007-11-30 20:51:32 +01003891 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003893
3894 if (strcmp(args[1], "fail") == 0) {
3895 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003896 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003897 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3898 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003901 }
3902
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003903 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3904 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3905 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003908 }
3909 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3910 }
3911 else {
3912 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003915 }
3916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917#ifdef TPROXY
3918 else if (!strcmp(args[0], "transparent")) {
3919 /* enable transparent proxy connections */
3920 curproxy->options |= PR_O_TRANSP;
3921 }
3922#endif
3923 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003924 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003926
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927 if (*(args[1]) == 0) {
3928 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931 }
3932 curproxy->maxconn = atol(args[1]);
3933 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003934 else if (!strcmp(args[0], "backlog")) { /* backlog */
3935 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003936 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003937
3938 if (*(args[1]) == 0) {
3939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003942 }
3943 curproxy->backlog = atol(args[1]);
3944 }
Willy Tarreau86034312006-12-29 00:10:33 +01003945 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003946 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003948
Willy Tarreau86034312006-12-29 00:10:33 +01003949 if (*(args[1]) == 0) {
3950 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003953 }
3954 curproxy->fullconn = atol(args[1]);
3955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3957 if (*(args[1]) == 0) {
3958 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003962 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3963 if (err) {
3964 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3965 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003968 }
3969 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 }
3971 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003972 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003973 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003974 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003975
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 if (curproxy == &defproxy) {
3977 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003980 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003981 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003982 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003983
Willy Tarreau902636f2013-03-10 19:44:48 +01003984 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003985 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01003986 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003987 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003988 goto out;
3989 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003990
3991 proto = protocol_by_family(sk->ss_family);
3992 if (!proto || !proto->connect) {
3993 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
3994 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
3997 }
3998
3999 if (port1 != port2) {
4000 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4001 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004005
4006 if (!port1) {
4007 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4008 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
4011 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004012
Willy Tarreaud5191e72010-02-09 20:50:45 +01004013 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004014 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 }
4016 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004017 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004019
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004020 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4021 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004026 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4027 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4028 err_code |= ERR_WARN;
4029
4030 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4031 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4032 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4033 }
4034 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4035 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4036 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4037 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004038 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4039 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4040 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4041 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004042 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004043 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004048 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004050 short realport = 0;
4051 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004052
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004053 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004057 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004058 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004059 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060
4061 if (!*args[2]) {
4062 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4063 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004066 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004067
4068 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004069 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004070 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4071 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004074 }
4075
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004076 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004077 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004078 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004079 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004080
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004081 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4082 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4083 err_code |= ERR_ALERT | ERR_ABORT;
4084 goto out;
4085 }
4086
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004087 /* the servers are linked backwards first */
4088 newsrv->next = curproxy->srv;
4089 curproxy->srv = newsrv;
4090 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004091 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004092 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004093
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004094 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004095 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004096 LIST_INIT(&newsrv->pendconns);
4097 do_check = 0;
4098 newsrv->state = SRV_RUNNING; /* early server setup */
4099 newsrv->last_change = now.tv_sec;
4100 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004101
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004102 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004103 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004104 * - IP: => port=+0, relative
4105 * - IP:N => port=N, absolute
4106 * - IP:+N => port=+N, relative
4107 * - IP:-N => port=-N, relative
4108 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004109 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004110 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004111 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004112 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004113 goto out;
4114 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004115
4116 proto = protocol_by_family(sk->ss_family);
4117 if (!proto || !proto->connect) {
4118 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4119 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
4122 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004123
4124 if (!port1 || !port2) {
4125 /* no port specified, +offset, -offset */
4126 newsrv->state |= SRV_MAPPORTS;
4127 }
4128 else if (port1 != port2) {
4129 /* port range */
4130 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4131 file, linenum, args[0], args[1], args[2]);
4132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
4134 }
4135 else {
4136 /* used by checks */
4137 realport = port1;
4138 }
4139
Willy Tarreaud5191e72010-02-09 20:50:45 +01004140 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004141 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4142 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004143
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004144 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004145 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4146 file, linenum, newsrv->addr.ss_family, args[2]);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004150
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004151 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004152 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 newsrv->inter = curproxy->defsrv.inter;
4154 newsrv->fastinter = curproxy->defsrv.fastinter;
4155 newsrv->downinter = curproxy->defsrv.downinter;
4156 newsrv->rise = curproxy->defsrv.rise;
4157 newsrv->fall = curproxy->defsrv.fall;
4158 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4159 newsrv->minconn = curproxy->defsrv.minconn;
4160 newsrv->maxconn = curproxy->defsrv.maxconn;
4161 newsrv->slowstart = curproxy->defsrv.slowstart;
4162 newsrv->onerror = curproxy->defsrv.onerror;
4163 newsrv->consecutive_errors_limit
4164 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004165#ifdef OPENSSL
4166 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4167#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004168 newsrv->uweight = newsrv->iweight
4169 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004171 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004172
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004173 cur_arg = 3;
4174 } else {
4175 newsrv = &curproxy->defsrv;
4176 cur_arg = 1;
4177 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004178
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004180 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 newsrv->cookie = strdup(args[cur_arg + 1]);
4182 newsrv->cklen = strlen(args[cur_arg + 1]);
4183 cur_arg += 2;
4184 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004185 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004186 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4187 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4188 cur_arg += 2;
4189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004191 if (!*args[cur_arg + 1]) {
4192 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4193 file, linenum, args[cur_arg]);
4194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
4196 }
4197
Willy Tarreaubaaee002006-06-26 02:48:02 +02004198 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004199 if (newsrv->rise <= 0) {
4200 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4201 file, linenum, args[cur_arg]);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 }
4205
Willy Tarreau96839092010-03-29 10:02:24 +02004206 if (newsrv->health)
4207 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208 cur_arg += 2;
4209 }
4210 else if (!strcmp(args[cur_arg], "fall")) {
4211 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004212
4213 if (!*args[cur_arg + 1]) {
4214 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4215 file, linenum, args[cur_arg]);
4216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
4218 }
4219
4220 if (newsrv->fall <= 0) {
4221 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4222 file, linenum, args[cur_arg]);
4223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
4225 }
4226
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 cur_arg += 2;
4228 }
4229 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004230 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4231 if (err) {
4232 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4233 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004236 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004237 if (val <= 0) {
4238 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4239 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004242 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004243 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 cur_arg += 2;
4245 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004246 else if (!strcmp(args[cur_arg], "fastinter")) {
4247 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4248 if (err) {
4249 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4250 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004253 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004254 if (val <= 0) {
4255 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4256 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004259 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004260 newsrv->fastinter = val;
4261 cur_arg += 2;
4262 }
4263 else if (!strcmp(args[cur_arg], "downinter")) {
4264 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4265 if (err) {
4266 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4267 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004270 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004271 if (val <= 0) {
4272 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4273 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004276 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004277 newsrv->downinter = val;
4278 cur_arg += 2;
4279 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004280 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004281 struct sockaddr_storage *sk;
4282 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004283 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004284
Willy Tarreau902636f2013-03-10 19:44:48 +01004285 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004286 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004287 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004288 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004289 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004290 goto out;
4291 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004292
4293 proto = protocol_by_family(sk->ss_family);
4294 if (!proto || !proto->connect) {
4295 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004296 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
4299 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004300
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004301 if (port1 != port2) {
4302 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4303 file, linenum, args[cur_arg], args[cur_arg + 1]);
4304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
4306 }
4307
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004308 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004309 cur_arg += 2;
4310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004312 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004313 cur_arg += 2;
4314 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004315 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 newsrv->state |= SRV_BACKUP;
4317 cur_arg ++;
4318 }
Simon Hormanfa461682011-06-25 09:39:49 +09004319 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4320 newsrv->state |= SRV_NON_STICK;
4321 cur_arg ++;
4322 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004323 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4324 newsrv->state |= SRV_SEND_PROXY;
4325 cur_arg ++;
4326 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004327 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4328 newsrv->check.send_proxy = 1;
4329 cur_arg ++;
4330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 else if (!strcmp(args[cur_arg], "weight")) {
4332 int w;
4333 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004334 if (w < 0 || w > 256) {
4335 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004340 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004341 cur_arg += 2;
4342 }
4343 else if (!strcmp(args[cur_arg], "minconn")) {
4344 newsrv->minconn = atol(args[cur_arg + 1]);
4345 cur_arg += 2;
4346 }
4347 else if (!strcmp(args[cur_arg], "maxconn")) {
4348 newsrv->maxconn = atol(args[cur_arg + 1]);
4349 cur_arg += 2;
4350 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004351 else if (!strcmp(args[cur_arg], "maxqueue")) {
4352 newsrv->maxqueue = atol(args[cur_arg + 1]);
4353 cur_arg += 2;
4354 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004355 else if (!strcmp(args[cur_arg], "slowstart")) {
4356 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004357 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004358 if (err) {
4359 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4360 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004363 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004364 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004365 cur_arg += 2;
4366 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004367 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004368
4369 if (!*args[cur_arg + 1]) {
4370 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4371 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004374 }
4375
4376 newsrv->trackit = strdup(args[cur_arg + 1]);
4377
4378 cur_arg += 2;
4379 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004380 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004381 global.maxsock++;
4382 do_check = 1;
4383 cur_arg += 1;
4384 }
Willy Tarreau96839092010-03-29 10:02:24 +02004385 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4386 newsrv->state |= SRV_MAINTAIN;
4387 newsrv->state &= ~SRV_RUNNING;
4388 newsrv->health = 0;
4389 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004390 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004391 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004392 if (!strcmp(args[cur_arg + 1], "none"))
4393 newsrv->observe = HANA_OBS_NONE;
4394 else if (!strcmp(args[cur_arg + 1], "layer4"))
4395 newsrv->observe = HANA_OBS_LAYER4;
4396 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4397 if (curproxy->mode != PR_MODE_HTTP) {
4398 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4399 file, linenum, args[cur_arg + 1]);
4400 err_code |= ERR_ALERT;
4401 }
4402 newsrv->observe = HANA_OBS_LAYER7;
4403 }
4404 else {
4405 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004406 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004407 file, linenum, args[cur_arg], args[cur_arg + 1]);
4408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
4410 }
4411
4412 cur_arg += 2;
4413 }
4414 else if (!strcmp(args[cur_arg], "on-error")) {
4415 if (!strcmp(args[cur_arg + 1], "fastinter"))
4416 newsrv->onerror = HANA_ONERR_FASTINTER;
4417 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4418 newsrv->onerror = HANA_ONERR_FAILCHK;
4419 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4420 newsrv->onerror = HANA_ONERR_SUDDTH;
4421 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4422 newsrv->onerror = HANA_ONERR_MARKDWN;
4423 else {
4424 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004425 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004426 file, linenum, args[cur_arg], args[cur_arg + 1]);
4427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
4429 }
4430
4431 cur_arg += 2;
4432 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004433 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4434 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4435 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4436 else {
4437 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4438 file, linenum, args[cur_arg], args[cur_arg + 1]);
4439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
4441 }
4442
4443 cur_arg += 2;
4444 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004445 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4446 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4447 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4448 else {
4449 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4450 file, linenum, args[cur_arg], args[cur_arg + 1]);
4451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
4453 }
4454
4455 cur_arg += 2;
4456 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004457 else if (!strcmp(args[cur_arg], "error-limit")) {
4458 if (!*args[cur_arg + 1]) {
4459 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4460 file, linenum, args[cur_arg]);
4461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
4463 }
4464
4465 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4466
4467 if (newsrv->consecutive_errors_limit <= 0) {
4468 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4469 file, linenum, args[cur_arg]);
4470 err_code |= ERR_ALERT | ERR_FATAL;
4471 goto out;
4472 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004473 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004474 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004475 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004476 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004477 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004478 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004479
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004481 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4482 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004486
Willy Tarreauef9a3602012-12-08 22:29:20 +01004487 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004488 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004489 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004490 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004491 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004492 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004493 goto out;
4494 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004495
4496 proto = protocol_by_family(sk->ss_family);
4497 if (!proto || !proto->connect) {
4498 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4499 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
4502 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004503
Willy Tarreauef9a3602012-12-08 22:29:20 +01004504 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004505
4506 if (port_low != port_high) {
4507 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004508
4509 if (!port_low || !port_high) {
4510 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4511 file, linenum, args[cur_arg], args[cur_arg + 1]);
4512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
4514 }
4515
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004516 if (port_low <= 0 || port_low > 65535 ||
4517 port_high <= 0 || port_high > 65535 ||
4518 port_low > port_high) {
4519 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4520 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004523 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004524 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4525 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4526 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004527 }
4528
Willy Tarreaubaaee002006-06-26 02:48:02 +02004529 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004530 while (*(args[cur_arg])) {
4531 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004532#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4533#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004534 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004535 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4536 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004539 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004540#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004541 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004542 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004543 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004544 err_code |= ERR_ALERT | ERR_FATAL;
4545 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004546 }
4547 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004548 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4549 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004550 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004551 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4552 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004553 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4554 char *name, *end;
4555
4556 name = args[cur_arg+1] + 7;
4557 while (isspace(*name))
4558 name++;
4559
4560 end = name;
4561 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4562 end++;
4563
Willy Tarreauef9a3602012-12-08 22:29:20 +01004564 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4565 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4566 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4567 newsrv->conn_src.bind_hdr_len = end - name;
4568 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4569 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4570 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004571
4572 /* now look for an occurrence number */
4573 while (isspace(*end))
4574 end++;
4575 if (*end == ',') {
4576 end++;
4577 name = end;
4578 if (*end == '-')
4579 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004580 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004581 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004582 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004583 }
4584
Willy Tarreauef9a3602012-12-08 22:29:20 +01004585 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004586 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4587 " occurrences values smaller than %d.\n",
4588 file, linenum, MAX_HDR_HISTORY);
4589 err_code |= ERR_ALERT | ERR_FATAL;
4590 goto out;
4591 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004592 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004593 struct sockaddr_storage *sk;
4594 int port1, port2;
4595
Willy Tarreau902636f2013-03-10 19:44:48 +01004596 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004597 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004598 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004599 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004600 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004601 goto out;
4602 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004603
4604 proto = protocol_by_family(sk->ss_family);
4605 if (!proto || !proto->connect) {
4606 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4607 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
4610 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004611
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004612 if (port1 != port2) {
4613 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4614 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
4617 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004618 newsrv->conn_src.tproxy_addr = *sk;
4619 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004620 }
4621 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004622#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004623 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004624#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004625 cur_arg += 2;
4626 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004627#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004628 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004629 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004632#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4633 } /* "usesrc" */
4634
4635 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4636#ifdef SO_BINDTODEVICE
4637 if (!*args[cur_arg + 1]) {
4638 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4639 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004642 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004643 free(newsrv->conn_src.iface_name);
4644 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4645 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004646 global.last_checks |= LSTCHK_NETADM;
4647#else
4648 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4649 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004652#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004653 cur_arg += 2;
4654 continue;
4655 }
4656 /* this keyword in not an option of "source" */
4657 break;
4658 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004660 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004661 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4662 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004666 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004667 static int srv_dumped;
4668 struct srv_kw *kw;
4669 char *err;
4670
4671 kw = srv_find_kw(args[cur_arg]);
4672 if (kw) {
4673 char *err = NULL;
4674 int code;
4675
4676 if (!kw->parse) {
4677 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4678 file, linenum, args[0], args[1], args[cur_arg]);
4679 cur_arg += 1 + kw->skip ;
4680 err_code |= ERR_ALERT | ERR_FATAL;
4681 goto out;
4682 }
4683
4684 if (defsrv && !kw->default_ok) {
4685 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4686 file, linenum, args[0], args[1], args[cur_arg]);
4687 cur_arg += 1 + kw->skip ;
4688 err_code |= ERR_ALERT;
4689 continue;
4690 }
4691
4692 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4693 err_code |= code;
4694
4695 if (code) {
4696 if (err && *err) {
4697 indent_msg(&err, 2);
4698 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4699 }
4700 else
4701 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4702 file, linenum, args[0], args[1], args[cur_arg]);
4703 if (code & ERR_FATAL) {
4704 free(err);
4705 cur_arg += 1 + kw->skip;
4706 goto out;
4707 }
4708 }
4709 free(err);
4710 cur_arg += 1 + kw->skip;
4711 continue;
4712 }
4713
4714 err = NULL;
4715 if (!srv_dumped) {
4716 srv_dump_kws(&err);
4717 indent_msg(&err, 4);
4718 srv_dumped = 1;
4719 }
4720
4721 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4722 file, linenum, args[0], args[1], args[cur_arg],
4723 err ? " Registered keywords :" : "", err ? err : "");
4724 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004725
Willy Tarreau93893792009-07-23 13:19:11 +02004726 err_code |= ERR_ALERT | ERR_FATAL;
4727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004728 }
4729 }
4730
4731 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004732 if (newsrv->trackit) {
4733 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4734 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004737 }
4738
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004739 /* If neither a port nor an addr was specified and no check transport
4740 * layer is forced, then the transport layer used by the checks is the
4741 * same as for the production traffic. Otherwise we use raw_sock by
4742 * default, unless one is specified.
4743 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004744 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004745#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004746 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004747#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004748 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4749 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004750 /* try to get the port from check.addr if check.port not set */
4751 if (!newsrv->check.port)
4752 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004753
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004754 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004755 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004756
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004757 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004758 /* not yet valid, because no port was set on
4759 * the server either. We'll check if we have
4760 * a known port on the first listener.
4761 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004762 struct listener *l;
4763
4764 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004765 newsrv->check.port = get_host_port(&l->addr);
4766 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004767 break;
4768 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004769 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004770 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4772 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004773 err_code |= ERR_ALERT | ERR_FATAL;
4774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004776
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004777 /* Allocate buffer for check requests... */
4778 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004779 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4780 err_code |= ERR_ALERT | ERR_ABORT;
4781 goto out;
4782 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004783 newsrv->check.bi->size = global.tune.chksize;
4784
4785 /* Allocate buffer for check responses... */
4786 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4787 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4788 err_code |= ERR_ALERT | ERR_ABORT;
4789 goto out;
4790 }
4791 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004792
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004793 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004794 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004795 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4796 err_code |= ERR_ALERT | ERR_ABORT;
4797 goto out;
4798 }
4799
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004800 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4801 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004802 newsrv->state |= SRV_CHECKED;
4803 }
4804
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004805 if (!defsrv) {
4806 if (newsrv->state & SRV_BACKUP)
4807 curproxy->srv_bck++;
4808 else
4809 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004810
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004811 newsrv->prev_state = newsrv->state;
4812 }
William Lallemanda73203e2012-03-12 12:48:57 +01004813 }
4814
4815 else if (strcmp(args[0], "unique-id-format") == 0) {
4816 if (!*(args[1])) {
4817 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
4820 }
William Lallemand3203ff42012-11-11 17:30:56 +01004821 if (*(args[2])) {
4822 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4823 err_code |= ERR_ALERT | ERR_FATAL;
4824 goto out;
4825 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004826 free(curproxy->uniqueid_format_string);
4827 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004828 }
William Lallemanda73203e2012-03-12 12:48:57 +01004829
4830 else if (strcmp(args[0], "unique-id-header") == 0) {
4831 if (!*(args[1])) {
4832 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
4835 }
4836 free(curproxy->header_unique_id);
4837 curproxy->header_unique_id = strdup(args[1]);
4838 }
4839
William Lallemand723b73a2012-02-08 16:37:49 +01004840 else if (strcmp(args[0], "log-format") == 0) {
4841 if (!*(args[1])) {
4842 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4843 err_code |= ERR_ALERT | ERR_FATAL;
4844 goto out;
4845 }
William Lallemand3203ff42012-11-11 17:30:56 +01004846 if (*(args[2])) {
4847 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
4850 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004851
4852 if (curproxy->logformat_string != default_http_log_format &&
4853 curproxy->logformat_string != default_tcp_log_format &&
4854 curproxy->logformat_string != clf_http_log_format)
4855 free(curproxy->logformat_string);
4856 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 }
William Lallemand723b73a2012-02-08 16:37:49 +01004858
William Lallemand0f99e342011-10-12 17:50:54 +02004859 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4860 /* delete previous herited or defined syslog servers */
4861 struct logsrv *back;
4862
4863 if (*(args[1]) != 0) {
4864 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
4868
William Lallemand723b73a2012-02-08 16:37:49 +01004869 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4870 LIST_DEL(&tmplogsrv->list);
4871 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004872 }
4873 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004875 struct logsrv *logsrv;
4876
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004878 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004879 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004880 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004881 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004882 LIST_INIT(&node->list);
4883 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4884 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004885 }
4886 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004887 struct sockaddr_storage *sk;
4888 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004889
4890 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891
William Lallemand0f99e342011-10-12 17:50:54 +02004892 logsrv->facility = get_log_facility(args[2]);
4893 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004895 err_code |= ERR_ALERT | ERR_FATAL;
4896 goto out;
4897
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 }
4899
William Lallemand0f99e342011-10-12 17:50:54 +02004900 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004902 logsrv->level = get_log_level(args[3]);
4903 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
4907
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 }
4909 }
4910
William Lallemand0f99e342011-10-12 17:50:54 +02004911 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004912 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004913 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004914 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004915 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004919 }
4920 }
4921
Willy Tarreau902636f2013-03-10 19:44:48 +01004922 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004923 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004924 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004925 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004926 goto out;
4927 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004928
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004929 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004930
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004931 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004932 if (port1 != port2) {
4933 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4934 file, linenum, args[0], args[1]);
4935 err_code |= ERR_ALERT | ERR_FATAL;
4936 goto out;
4937 }
4938
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004939 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004940 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 }
William Lallemand0f99e342011-10-12 17:50:54 +02004942
4943 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
4945 else {
4946 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4947 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
4951 }
4952 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004953 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004954 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004955 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004956 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004957
Willy Tarreau977b8e42006-12-29 14:19:17 +01004958 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004959 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004960
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004962 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4963 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004967
4968 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004969 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4970 free(curproxy->conn_src.iface_name);
4971 curproxy->conn_src.iface_name = NULL;
4972 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004973
Willy Tarreau902636f2013-03-10 19:44:48 +01004974 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004975 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004976 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004977 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004978 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004979 goto out;
4980 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004981
4982 proto = protocol_by_family(sk->ss_family);
4983 if (!proto || !proto->connect) {
4984 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004985 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
4988 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004989
4990 if (port1 != port2) {
4991 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4992 file, linenum, args[0], args[1]);
4993 err_code |= ERR_ALERT | ERR_FATAL;
4994 goto out;
4995 }
4996
Willy Tarreauef9a3602012-12-08 22:29:20 +01004997 curproxy->conn_src.source_addr = *sk;
4998 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004999
5000 cur_arg = 2;
5001 while (*(args[cur_arg])) {
5002 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005003#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
5004#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005005 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005006 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5007 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005010 }
5011#endif
5012 if (!*args[cur_arg + 1]) {
5013 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5014 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005017 }
5018
5019 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005020 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5021 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005022 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005023 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5024 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005025 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5026 char *name, *end;
5027
5028 name = args[cur_arg+1] + 7;
5029 while (isspace(*name))
5030 name++;
5031
5032 end = name;
5033 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5034 end++;
5035
Willy Tarreauef9a3602012-12-08 22:29:20 +01005036 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5037 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5038 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5039 curproxy->conn_src.bind_hdr_len = end - name;
5040 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5041 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5042 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005043
5044 /* now look for an occurrence number */
5045 while (isspace(*end))
5046 end++;
5047 if (*end == ',') {
5048 end++;
5049 name = end;
5050 if (*end == '-')
5051 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005052 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005053 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005054 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005055 }
5056
Willy Tarreauef9a3602012-12-08 22:29:20 +01005057 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005058 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5059 " occurrences values smaller than %d.\n",
5060 file, linenum, MAX_HDR_HISTORY);
5061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
5063 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005064 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005065 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005066
Willy Tarreau902636f2013-03-10 19:44:48 +01005067 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005068 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005069 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005070 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005071 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005072 goto out;
5073 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005074
5075 proto = protocol_by_family(sk->ss_family);
5076 if (!proto || !proto->connect) {
5077 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5078 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005079 err_code |= ERR_ALERT | ERR_FATAL;
5080 goto out;
5081 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005082
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005083 if (port1 != port2) {
5084 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5085 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
5088 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005089 curproxy->conn_src.tproxy_addr = *sk;
5090 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005091 }
5092 global.last_checks |= LSTCHK_NETADM;
5093#if !defined(CONFIG_HAP_LINUX_TPROXY)
5094 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005095#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005096#else /* no TPROXY support */
5097 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005098 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005101#endif
5102 cur_arg += 2;
5103 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005104 }
5105
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005106 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5107#ifdef SO_BINDTODEVICE
5108 if (!*args[cur_arg + 1]) {
5109 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5110 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005111 err_code |= ERR_ALERT | ERR_FATAL;
5112 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005113 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005114 free(curproxy->conn_src.iface_name);
5115 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5116 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005117 global.last_checks |= LSTCHK_NETADM;
5118#else
5119 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5120 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005123#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005124 cur_arg += 2;
5125 continue;
5126 }
5127 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005128 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005132 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005133 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5134 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5135 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005141 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5142 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005146
5147 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005148 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005149 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005150 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 }
5153 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005154 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005155 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005156 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005157 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 }
5160 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005161 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005162 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005163 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005164 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
5167 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005169 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005170 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005171 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 }
5174 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005175 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005176 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005177 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005181 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005182 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005183 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005184 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005186 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005187 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005188 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005190 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005191 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005193 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005194 }
5195 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005196 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005197 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005198 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005200 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005203 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005208 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005209
5210 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005211 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005212 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005213 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005215 }
5216 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005217 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005218 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005219 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005220 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 }
5223 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005224 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005225 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005226 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005227 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
5230 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005231 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005232 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005233 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005234 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 }
5237 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005238 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005239 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005240 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005241 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005243 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005244 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005245 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005246 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005247 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005248 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005249 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005251 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005252 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005253
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 if (curproxy == &defproxy) {
5255 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005256 err_code |= ERR_ALERT | ERR_FATAL;
5257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005259 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005260 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 if (*(args[1]) == 0) {
5263 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005267
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005268 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005269 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5270 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5271 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
5274 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005275 err_code |= warnif_cond_conflicts(cond,
5276 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5277 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005278 }
5279 else if (*args[2]) {
5280 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5281 file, linenum, args[0], args[2]);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005286 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005287 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005288 wl->s = strdup(args[1]);
5289 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005290 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 }
5292 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005293 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5295 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005299
Willy Tarreauade5ec42010-01-28 19:33:49 +01005300 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005301 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005302 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005303 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
5306 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005307 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005308 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005309 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005310 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
5313 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005315 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005316 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005317 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 }
5320 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005321 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5323 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005324 err_code |= ERR_ALERT | ERR_FATAL;
5325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 }
5327
Willy Tarreauade5ec42010-01-28 19:33:49 +01005328 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005329 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005330 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005331 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 }
5334 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005335 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005336 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005337 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005338 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 }
5341 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005342 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005343 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005344 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005345 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 }
5348 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005349 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005350
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 if (curproxy == &defproxy) {
5352 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005353 err_code |= ERR_ALERT | ERR_FATAL;
5354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005355 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005356 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005357 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359 if (*(args[1]) == 0) {
5360 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 }
5364
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005365 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005366 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5367 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5368 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
5371 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005372 err_code |= warnif_cond_conflicts(cond,
5373 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5374 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005375 }
5376 else if (*args[2]) {
5377 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5378 file, linenum, args[0], args[2]);
5379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
5381 }
5382
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005383 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005384 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005385 wl->s = strdup(args[1]);
5386 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005387 }
5388 else if (!strcmp(args[0], "errorloc") ||
5389 !strcmp(args[0], "errorloc302") ||
5390 !strcmp(args[0], "errorloc303")) { /* error location */
5391 int errnum, errlen;
5392 char *err;
5393
Willy Tarreau977b8e42006-12-29 14:19:17 +01005394 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005395 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005396
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005398 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 }
5402
5403 errnum = atol(args[1]);
5404 if (!strcmp(args[0], "errorloc303")) {
5405 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5406 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5407 } else {
5408 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5409 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5410 }
5411
Willy Tarreau0f772532006-12-23 20:51:41 +01005412 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5413 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005414 chunk_destroy(&curproxy->errmsg[rc]);
5415 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005416 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005418 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005419
5420 if (rc >= HTTP_ERR_SIZE) {
5421 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5422 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005423 free(err);
5424 }
5425 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005426 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5427 int errnum, errlen, fd;
5428 char *err;
5429 struct stat stat;
5430
5431 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005432 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005433
5434 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005435 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005436 err_code |= ERR_ALERT | ERR_FATAL;
5437 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005438 }
5439
5440 fd = open(args[2], O_RDONLY);
5441 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5442 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5443 file, linenum, args[2], args[1]);
5444 if (fd >= 0)
5445 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005448 }
5449
Willy Tarreau27a674e2009-08-17 07:23:33 +02005450 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005451 errlen = stat.st_size;
5452 } else {
5453 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005454 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005455 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005456 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005457 }
5458
5459 err = malloc(errlen); /* malloc() must succeed during parsing */
5460 errnum = read(fd, err, errlen);
5461 if (errnum != errlen) {
5462 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5463 file, linenum, args[2], args[1]);
5464 close(fd);
5465 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005468 }
5469 close(fd);
5470
5471 errnum = atol(args[1]);
5472 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5473 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005474 chunk_destroy(&curproxy->errmsg[rc]);
5475 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005476 break;
5477 }
5478 }
5479
5480 if (rc >= HTTP_ERR_SIZE) {
5481 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5482 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005483 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005484 free(err);
5485 }
5486 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005487 else if (!strcmp(args[0], "compression")) {
5488 struct comp *comp;
5489 if (curproxy->comp == NULL) {
5490 comp = calloc(1, sizeof(struct comp));
5491 curproxy->comp = comp;
5492 } else {
5493 comp = curproxy->comp;
5494 }
5495
5496 if (!strcmp(args[1], "algo")) {
5497 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005498 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005499
William Lallemand82fe75c2012-10-23 10:25:10 +02005500 cur_arg = 2;
5501 if (!*args[cur_arg]) {
5502 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5503 file, linenum, args[0]);
5504 err_code |= ERR_ALERT | ERR_FATAL;
5505 goto out;
5506 }
5507 while (*(args[cur_arg])) {
5508 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5509 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5510 file, linenum, args[0], args[cur_arg]);
5511 err_code |= ERR_ALERT | ERR_FATAL;
5512 goto out;
5513 }
William Lallemand552df672012-11-07 13:21:47 +01005514 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5515 curproxy->comp->algos->end(&ctx);
5516 } else {
5517 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5518 file, linenum, args[0], args[cur_arg]);
5519 err_code |= ERR_ALERT | ERR_FATAL;
5520 goto out;
5521 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005522 cur_arg ++;
5523 continue;
5524 }
5525 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005526 else if (!strcmp(args[1], "offload")) {
5527 comp->offload = 1;
5528 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005529 else if (!strcmp(args[1], "type")) {
5530 int cur_arg;
5531 cur_arg = 2;
5532 if (!*args[cur_arg]) {
5533 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5534 file, linenum, args[0]);
5535 err_code |= ERR_ALERT | ERR_FATAL;
5536 goto out;
5537 }
5538 while (*(args[cur_arg])) {
5539 comp_append_type(comp, args[cur_arg]);
5540 cur_arg ++;
5541 continue;
5542 }
5543 }
5544 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005545 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005546 file, linenum, args[0]);
5547 err_code |= ERR_ALERT | ERR_FATAL;
5548 goto out;
5549 }
5550 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005551 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005552 struct cfg_kw_list *kwl;
5553 int index;
5554
5555 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5556 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5557 if (kwl->kw[index].section != CFG_LISTEN)
5558 continue;
5559 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5560 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005561 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005562 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005563 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005566 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005567 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005568 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005569 err_code |= ERR_WARN;
5570 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005571 }
Willy Tarreau93893792009-07-23 13:19:11 +02005572 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005573 }
5574 }
5575 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005576
Willy Tarreau6daf3432008-01-22 16:44:08 +01005577 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005578 err_code |= ERR_ALERT | ERR_FATAL;
5579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 }
Willy Tarreau93893792009-07-23 13:19:11 +02005581 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005582 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005583 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584}
5585
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005586int
5587cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5588{
5589
5590 int err_code = 0;
5591 const char *err;
5592
5593 if (!strcmp(args[0], "userlist")) { /* new userlist */
5594 struct userlist *newul;
5595
5596 if (!*args[1]) {
5597 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5598 file, linenum, args[0]);
5599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
5601 }
5602
5603 err = invalid_char(args[1]);
5604 if (err) {
5605 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5606 file, linenum, *err, args[0], args[1]);
5607 err_code |= ERR_ALERT | ERR_FATAL;
5608 goto out;
5609 }
5610
5611 for (newul = userlist; newul; newul = newul->next)
5612 if (!strcmp(newul->name, args[1])) {
5613 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5614 file, linenum, args[1]);
5615 err_code |= ERR_WARN;
5616 goto out;
5617 }
5618
5619 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5620 if (!newul) {
5621 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5622 err_code |= ERR_ALERT | ERR_ABORT;
5623 goto out;
5624 }
5625
5626 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5627 newul->name = strdup(args[1]);
5628
5629 if (!newul->groupusers | !newul->name) {
5630 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5631 err_code |= ERR_ALERT | ERR_ABORT;
5632 goto out;
5633 }
5634
5635 newul->next = userlist;
5636 userlist = newul;
5637
5638 } else if (!strcmp(args[0], "group")) { /* new group */
5639 int cur_arg, i;
5640 const char *err;
5641
5642 if (!*args[1]) {
5643 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5644 file, linenum, args[0]);
5645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
5647 }
5648
5649 err = invalid_char(args[1]);
5650 if (err) {
5651 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5652 file, linenum, *err, args[0], args[1]);
5653 err_code |= ERR_ALERT | ERR_FATAL;
5654 goto out;
5655 }
5656
5657 for(i = 0; i < userlist->grpcnt; i++)
5658 if (!strcmp(userlist->groups[i], args[1])) {
5659 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5660 file, linenum, args[1], userlist->name);
5661 err_code |= ERR_ALERT;
5662 goto out;
5663 }
5664
5665 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5666 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5667 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
5670 }
5671
5672 cur_arg = 2;
5673
5674 while (*args[cur_arg]) {
5675 if (!strcmp(args[cur_arg], "users")) {
5676 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5677 cur_arg += 2;
5678 continue;
5679 } else {
5680 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5681 file, linenum, args[0]);
5682 err_code |= ERR_ALERT | ERR_FATAL;
5683 goto out;
5684 }
5685 }
5686
5687 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5688 } else if (!strcmp(args[0], "user")) { /* new user */
5689 struct auth_users *newuser;
5690 int cur_arg;
5691
5692 if (!*args[1]) {
5693 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5694 file, linenum, args[0]);
5695 err_code |= ERR_ALERT | ERR_FATAL;
5696 goto out;
5697 }
5698
5699 for (newuser = userlist->users; newuser; newuser = newuser->next)
5700 if (!strcmp(newuser->user, args[1])) {
5701 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5702 file, linenum, args[1], userlist->name);
5703 err_code |= ERR_ALERT;
5704 goto out;
5705 }
5706
5707 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5708 if (!newuser) {
5709 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5710 err_code |= ERR_ALERT | ERR_ABORT;
5711 goto out;
5712 }
5713
5714 newuser->user = strdup(args[1]);
5715
5716 newuser->next = userlist->users;
5717 userlist->users = newuser;
5718
5719 cur_arg = 2;
5720
5721 while (*args[cur_arg]) {
5722 if (!strcmp(args[cur_arg], "password")) {
5723#ifndef CONFIG_HAP_CRYPT
5724 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5725 file, linenum);
5726 err_code |= ERR_ALERT;
5727#endif
5728 newuser->pass = strdup(args[cur_arg + 1]);
5729 cur_arg += 2;
5730 continue;
5731 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5732 newuser->pass = strdup(args[cur_arg + 1]);
5733 newuser->flags |= AU_O_INSECURE;
5734 cur_arg += 2;
5735 continue;
5736 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005737 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005738 cur_arg += 2;
5739 continue;
5740 } else {
5741 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5742 file, linenum, args[0]);
5743 err_code |= ERR_ALERT | ERR_FATAL;
5744 goto out;
5745 }
5746 }
5747 } else {
5748 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5749 err_code |= ERR_ALERT | ERR_FATAL;
5750 }
5751
5752out:
5753 return err_code;
5754}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755
5756/*
5757 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005758 * Returns the error code, 0 if OK, or any combination of :
5759 * - ERR_ABORT: must abort ASAP
5760 * - ERR_FATAL: we can continue parsing but not start the service
5761 * - ERR_WARN: a warning has been emitted
5762 * - ERR_ALERT: an alert has been emitted
5763 * Only the two first ones can stop processing, the two others are just
5764 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005766int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005768 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 FILE *f;
5770 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005772 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 if ((f=fopen(file,"r")) == NULL)
5775 return -1;
5776
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005777 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005778 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005779 char *end;
5780 char *args[MAX_LINE_ARGS + 1];
5781 char *line = thisline;
5782
Willy Tarreaubaaee002006-06-26 02:48:02 +02005783 linenum++;
5784
5785 end = line + strlen(line);
5786
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005787 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5788 /* Check if we reached the limit and the last char is not \n.
5789 * Watch out for the last line without the terminating '\n'!
5790 */
5791 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005792 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005793 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005794 }
5795
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005797 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 line++;
5799
5800 arg = 0;
5801 args[arg] = line;
5802
5803 while (*line && arg < MAX_LINE_ARGS) {
5804 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5805 * C equivalent value. Other combinations left unchanged (eg: \1).
5806 */
5807 if (*line == '\\') {
5808 int skip = 0;
5809 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5810 *line = line[1];
5811 skip = 1;
5812 }
5813 else if (line[1] == 'r') {
5814 *line = '\r';
5815 skip = 1;
5816 }
5817 else if (line[1] == 'n') {
5818 *line = '\n';
5819 skip = 1;
5820 }
5821 else if (line[1] == 't') {
5822 *line = '\t';
5823 skip = 1;
5824 }
5825 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005826 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 unsigned char hex1, hex2;
5828 hex1 = toupper(line[2]) - '0';
5829 hex2 = toupper(line[3]) - '0';
5830 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5831 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5832 *line = (hex1<<4) + hex2;
5833 skip = 3;
5834 }
5835 else {
5836 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005837 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005838 }
5839 }
5840 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005841 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 end -= skip;
5843 }
5844 line++;
5845 }
5846 else if (*line == '#' || *line == '\n' || *line == '\r') {
5847 /* end of string, end of loop */
5848 *line = 0;
5849 break;
5850 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005851 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005852 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005853 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005854 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005855 line++;
5856 args[++arg] = line;
5857 }
5858 else {
5859 line++;
5860 }
5861 }
5862
5863 /* empty line */
5864 if (!**args)
5865 continue;
5866
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005867 if (*line) {
5868 /* we had to stop due to too many args.
5869 * Let's terminate the string, print the offending part then cut the
5870 * last arg.
5871 */
5872 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5873 line++;
5874 *line = '\0';
5875
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005876 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005877 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005878 err_code |= ERR_ALERT | ERR_FATAL;
5879 args[arg] = line;
5880 }
5881
Willy Tarreau540abe42007-05-02 20:50:16 +02005882 /* zero out remaining args and ensure that at least one entry
5883 * is zeroed out.
5884 */
5885 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 args[arg] = line;
5887 }
5888
Willy Tarreau3842f002009-06-14 11:39:52 +02005889 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005890 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005891 char *tmp;
5892
Willy Tarreau3842f002009-06-14 11:39:52 +02005893 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005894 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005895 for (arg=0; *args[arg+1]; arg++)
5896 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005897 *tmp = '\0'; // fix the next arg to \0
5898 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005899 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005900 else if (!strcmp(args[0], "default")) {
5901 kwm = KWM_DEF;
5902 for (arg=0; *args[arg+1]; arg++)
5903 args[arg] = args[arg+1]; // shift args after inversion
5904 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005905
William Lallemand0f99e342011-10-12 17:50:54 +02005906 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5907 strcmp(args[0], "log") != 0) {
5908 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005909 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005910 }
5911
Willy Tarreau977b8e42006-12-29 14:19:17 +01005912 if (!strcmp(args[0], "listen") ||
5913 !strcmp(args[0], "frontend") ||
5914 !strcmp(args[0], "backend") ||
5915 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005916 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005918 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005919 cursection = strdup(args[0]);
5920 }
5921 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005923 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005924 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005925 }
5926 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005927 confsect = CFG_USERLIST;
5928 free(cursection);
5929 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005930 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005931 else if (!strcmp(args[0], "peers")) {
5932 confsect = CFG_PEERS;
5933 free(cursection);
5934 cursection = strdup(args[0]);
5935 }
5936
Willy Tarreaubaaee002006-06-26 02:48:02 +02005937 /* else it's a section keyword */
5938
5939 switch (confsect) {
5940 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005941 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005942 break;
5943 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005944 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005945 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005946 case CFG_USERLIST:
5947 err_code |= cfg_parse_users(file, linenum, args, kwm);
5948 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005949 case CFG_PEERS:
5950 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5951 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005952 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005953 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005954 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005955 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005956
5957 if (err_code & ERR_ABORT)
5958 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005959 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005960 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005961 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005962 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005963 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005964}
5965
Willy Tarreaubb925012009-07-23 13:36:36 +02005966/*
5967 * Returns the error code, 0 if OK, or any combination of :
5968 * - ERR_ABORT: must abort ASAP
5969 * - ERR_FATAL: we can continue parsing but not start the service
5970 * - ERR_WARN: a warning has been emitted
5971 * - ERR_ALERT: an alert has been emitted
5972 * Only the two first ones can stop processing, the two others are just
5973 * indicators.
5974 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005975int check_config_validity()
5976{
5977 int cfgerr = 0;
5978 struct proxy *curproxy = NULL;
5979 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005980 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005981 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005982 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005983 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005985 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005986 /*
5987 * Now, check for the integrity of all that we have collected.
5988 */
5989
5990 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005991 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005992
Willy Tarreau193b8c62012-11-22 00:17:38 +01005993 if (!global.tune.max_http_hdr)
5994 global.tune.max_http_hdr = MAX_HTTP_HDR;
5995
5996 if (!global.tune.cookie_len)
5997 global.tune.cookie_len = CAPTURE_LEN;
5998
5999 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6000
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006001 /* first, we will invert the proxy list order */
6002 curproxy = NULL;
6003 while (proxy) {
6004 struct proxy *next;
6005
6006 next = proxy->next;
6007 proxy->next = curproxy;
6008 curproxy = proxy;
6009 if (!next)
6010 break;
6011 proxy = next;
6012 }
6013
Willy Tarreaubaaee002006-06-26 02:48:02 +02006014 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006015 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006016 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006017 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006018 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006019 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006020 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006021 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006022
Willy Tarreau050536d2012-10-04 08:47:34 +02006023 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006024 /* proxy ID not set, use automatic numbering with first
6025 * spare entry starting with next_pxid.
6026 */
6027 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6028 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6029 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006030 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006031 next_pxid++;
6032
Willy Tarreau55ea7572007-06-17 19:56:27 +02006033
Willy Tarreaubaaee002006-06-26 02:48:02 +02006034 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006035 /* ensure we don't keep listeners uselessly bound */
6036 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006037 curproxy = curproxy->next;
6038 continue;
6039 }
6040
Willy Tarreau16a21472012-11-19 12:39:59 +01006041 /* number of processes this proxy is bound to */
6042 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6043
Willy Tarreauff01a212009-03-15 13:46:16 +01006044 switch (curproxy->mode) {
6045 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006046 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006047 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006048 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6049 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006050 cfgerr++;
6051 }
6052
6053 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006054 Warning("config : servers will be ignored for %s '%s'.\n",
6055 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006056 break;
6057
6058 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006059 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006060 break;
6061
6062 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006063 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006064 break;
6065 }
6066
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006067 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006068 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006069 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006070 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6071 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006072 cfgerr++;
6073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006074#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006075 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006076 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6077 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006078 cfgerr++;
6079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006080#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006081 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006082 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6083 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006084 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006085 }
6086 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006087 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006088 /* If no LB algo is set in a backend, and we're not in
6089 * transparent mode, dispatch mode nor proxy mode, we
6090 * want to use balance roundrobin by default.
6091 */
6092 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6093 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006094 }
6095 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006096
Willy Tarreau1620ec32011-08-06 17:05:02 +02006097 if (curproxy->options & PR_O_DISPATCH)
6098 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6099 else if (curproxy->options & PR_O_HTTP_PROXY)
6100 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6101 else if (curproxy->options & PR_O_TRANSP)
6102 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006103
Willy Tarreau1620ec32011-08-06 17:05:02 +02006104 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6105 if (curproxy->options & PR_O_DISABLE404) {
6106 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6107 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6108 err_code |= ERR_WARN;
6109 curproxy->options &= ~PR_O_DISABLE404;
6110 }
6111 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6112 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6113 "send-state", proxy_type_str(curproxy), curproxy->id);
6114 err_code |= ERR_WARN;
6115 curproxy->options &= ~PR_O2_CHK_SNDST;
6116 }
Willy Tarreauef781042010-01-27 11:53:01 +01006117 }
6118
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006119 /* if a default backend was specified, let's find it */
6120 if (curproxy->defbe.name) {
6121 struct proxy *target;
6122
Alex Williams96532db2009-11-01 21:27:13 -05006123 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006124 if (!target) {
6125 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6126 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006127 cfgerr++;
6128 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006129 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6130 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006131 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006132 } else {
6133 free(curproxy->defbe.name);
6134 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006135 /* we force the backend to be present on at least all of
6136 * the frontend's processes.
6137 */
6138 target->bind_proc = curproxy->bind_proc ?
6139 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006140
6141 /* Emit a warning if this proxy also has some servers */
6142 if (curproxy->srv) {
6143 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6144 curproxy->id);
6145 err_code |= ERR_WARN;
6146 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006147 }
6148 }
6149
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006150 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006151 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6152 /* map jump target for ACT_SETBE in req_rep chain */
6153 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006154 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006155 struct proxy *target;
6156
Willy Tarreaua496b602006-12-17 23:15:24 +01006157 if (exp->action != ACT_SETBE)
6158 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006159
Alex Williams96532db2009-11-01 21:27:13 -05006160 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006161 if (!target) {
6162 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6163 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006164 cfgerr++;
6165 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006166 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6167 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006168 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006169 } else {
6170 free((void *)exp->replace);
6171 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006172 /* we force the backend to be present on at least all of
6173 * the frontend's processes.
6174 */
6175 target->bind_proc = curproxy->bind_proc ?
6176 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006177 }
6178 }
6179 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006180
6181 /* find the target proxy for 'use_backend' rules */
6182 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006183 struct proxy *target;
6184
Alex Williams96532db2009-11-01 21:27:13 -05006185 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006186
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006187 if (!target) {
6188 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6189 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006190 cfgerr++;
6191 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006192 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6193 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006194 cfgerr++;
6195 } else {
6196 free((void *)rule->be.name);
6197 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006198 /* we force the backend to be present on at least all of
6199 * the frontend's processes.
6200 */
6201 target->bind_proc = curproxy->bind_proc ?
6202 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006203 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006204 }
6205
6206 /* find the target proxy for 'use_backend' rules */
6207 list_for_each_entry(srule, &curproxy->server_rules, list) {
6208 struct server *target = findserver(curproxy, srule->srv.name);
6209
6210 if (!target) {
6211 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6212 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6213 cfgerr++;
6214 continue;
6215 }
6216 free((void *)srule->srv.name);
6217 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006218 }
6219
Emeric Brunb982a3d2010-01-04 15:45:53 +01006220 /* find the target table for 'stick' rules */
6221 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6222 struct proxy *target;
6223
Emeric Brun1d33b292010-01-04 15:47:17 +01006224 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6225 if (mrule->flags & STK_IS_STORE)
6226 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6227
Emeric Brunb982a3d2010-01-04 15:45:53 +01006228 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006229 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006230 else
6231 target = curproxy;
6232
6233 if (!target) {
6234 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6235 curproxy->id, mrule->table.name);
6236 cfgerr++;
6237 }
6238 else if (target->table.size == 0) {
6239 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6240 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6241 cfgerr++;
6242 }
Willy Tarreau12785782012-04-27 21:37:17 +02006243 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6244 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006245 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6246 cfgerr++;
6247 }
6248 else {
6249 free((void *)mrule->table.name);
6250 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006251 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006252 }
6253 }
6254
6255 /* find the target table for 'store response' rules */
6256 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6257 struct proxy *target;
6258
Emeric Brun1d33b292010-01-04 15:47:17 +01006259 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6260
Emeric Brunb982a3d2010-01-04 15:45:53 +01006261 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006262 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006263 else
6264 target = curproxy;
6265
6266 if (!target) {
6267 Alert("Proxy '%s': unable to find store table '%s'.\n",
6268 curproxy->id, mrule->table.name);
6269 cfgerr++;
6270 }
6271 else if (target->table.size == 0) {
6272 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6273 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6274 cfgerr++;
6275 }
Willy Tarreau12785782012-04-27 21:37:17 +02006276 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6277 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006278 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6279 cfgerr++;
6280 }
6281 else {
6282 free((void *)mrule->table.name);
6283 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006284 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006285 }
6286 }
6287
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006288 /* find the target table for 'tcp-request' layer 4 rules */
6289 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6290 struct proxy *target;
6291
Willy Tarreau56123282010-08-06 19:06:56 +02006292 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006293 continue;
6294
6295 if (trule->act_prm.trk_ctr.table.n)
6296 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6297 else
6298 target = curproxy;
6299
6300 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006301 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6302 curproxy->id, trule->act_prm.trk_ctr.table.n,
6303 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006304 cfgerr++;
6305 }
6306 else if (target->table.size == 0) {
6307 Alert("Proxy '%s': table '%s' used but not configured.\n",
6308 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6309 cfgerr++;
6310 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006311 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6312 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6313 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6314 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6315 cfgerr++;
6316 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006317 else {
6318 free(trule->act_prm.trk_ctr.table.n);
6319 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006320 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006321 * to pass a list of counters to track and allocate them right here using
6322 * stktable_alloc_data_type().
6323 */
6324 }
6325 }
6326
Willy Tarreaud1f96522010-08-03 19:34:32 +02006327 /* find the target table for 'tcp-request' layer 6 rules */
6328 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6329 struct proxy *target;
6330
Willy Tarreau56123282010-08-06 19:06:56 +02006331 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006332 continue;
6333
6334 if (trule->act_prm.trk_ctr.table.n)
6335 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6336 else
6337 target = curproxy;
6338
6339 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006340 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6341 curproxy->id, trule->act_prm.trk_ctr.table.n,
6342 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006343 cfgerr++;
6344 }
6345 else if (target->table.size == 0) {
6346 Alert("Proxy '%s': table '%s' used but not configured.\n",
6347 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6348 cfgerr++;
6349 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006350 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6351 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6352 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6353 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6354 cfgerr++;
6355 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006356 else {
6357 free(trule->act_prm.trk_ctr.table.n);
6358 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006359 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006360 * to pass a list of counters to track and allocate them right here using
6361 * stktable_alloc_data_type().
6362 */
6363 }
6364 }
6365
Emeric Brun32da3c42010-09-23 18:39:19 +02006366 if (curproxy->table.peers.name) {
6367 struct peers *curpeers = peers;
6368
6369 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6370 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6371 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006372 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006373 break;
6374 }
6375 }
6376
6377 if (!curpeers) {
6378 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6379 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006380 free((void *)curproxy->table.peers.name);
6381 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006382 cfgerr++;
6383 }
6384 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006385 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6386 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006387 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006388 cfgerr++;
6389 }
6390 }
6391
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006392 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006393 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006394 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6395 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6396 "proxy", curproxy->id);
6397 cfgerr++;
6398 goto out_uri_auth_compat;
6399 }
6400
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006401 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006402 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006403 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006404 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006405
Willy Tarreau95fa4692010-02-01 13:05:50 +01006406 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6407 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006408
6409 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006410 uri_auth_compat_req[i++] = "realm";
6411 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6412 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006413
Willy Tarreau95fa4692010-02-01 13:05:50 +01006414 uri_auth_compat_req[i++] = "unless";
6415 uri_auth_compat_req[i++] = "{";
6416 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6417 uri_auth_compat_req[i++] = "}";
6418 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006419
Willy Tarreauff011f22011-01-06 17:51:27 +01006420 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6421 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006422 cfgerr++;
6423 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006424 }
6425
Willy Tarreauff011f22011-01-06 17:51:27 +01006426 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006427
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006428 if (curproxy->uri_auth->auth_realm) {
6429 free(curproxy->uri_auth->auth_realm);
6430 curproxy->uri_auth->auth_realm = NULL;
6431 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006432
6433 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006434 }
6435out_uri_auth_compat:
6436
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006437 cfgerr += acl_find_targets(curproxy);
6438
Willy Tarreau2738a142006-07-08 17:28:09 +02006439 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006440 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006441 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006442 (!curproxy->timeout.connect ||
6443 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006444 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006445 " | While not properly invalid, you will certainly encounter various problems\n"
6446 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006447 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006448 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006449 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006450 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006451
Willy Tarreau1fa31262007-12-03 00:36:16 +01006452 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6453 * We must still support older configurations, so let's find out whether those
6454 * parameters have been set or must be copied from contimeouts.
6455 */
6456 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006457 if (!curproxy->timeout.tarpit ||
6458 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006459 /* tarpit timeout not set. We search in the following order:
6460 * default.tarpit, curr.connect, default.connect.
6461 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006462 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006463 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006464 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006465 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006466 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006467 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006468 }
6469 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006470 (!curproxy->timeout.queue ||
6471 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006472 /* queue timeout not set. We search in the following order:
6473 * default.queue, curr.connect, default.connect.
6474 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006475 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006476 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006477 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006478 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006479 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006480 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006481 }
6482 }
6483
Willy Tarreau1620ec32011-08-06 17:05:02 +02006484 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006485 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6486 curproxy->check_req = (char *)malloc(curproxy->check_len);
6487 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006488 }
6489
Willy Tarreau193b8c62012-11-22 00:17:38 +01006490 /* ensure that cookie capture length is not too large */
6491 if (curproxy->capture_len >= global.tune.cookie_len) {
6492 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6493 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6494 err_code |= ERR_WARN;
6495 curproxy->capture_len = global.tune.cookie_len - 1;
6496 }
6497
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006498 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006499 if (curproxy->nb_req_cap) {
6500 if (curproxy->mode == PR_MODE_HTTP) {
6501 curproxy->req_cap_pool = create_pool("ptrcap",
6502 curproxy->nb_req_cap * sizeof(char *),
6503 MEM_F_SHARED);
6504 } else {
6505 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6506 proxy_type_str(curproxy), curproxy->id);
6507 err_code |= ERR_WARN;
6508 curproxy->to_log &= ~LW_REQHDR;
6509 curproxy->nb_req_cap = 0;
6510 }
6511 }
6512
6513 if (curproxy->nb_rsp_cap) {
6514 if (curproxy->mode == PR_MODE_HTTP) {
6515 curproxy->rsp_cap_pool = create_pool("ptrcap",
6516 curproxy->nb_rsp_cap * sizeof(char *),
6517 MEM_F_SHARED);
6518 } else {
6519 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6520 proxy_type_str(curproxy), curproxy->id);
6521 err_code |= ERR_WARN;
6522 curproxy->to_log &= ~LW_REQHDR;
6523 curproxy->nb_rsp_cap = 0;
6524 }
6525 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006526
Willy Tarreau196729e2012-05-31 19:30:26 +02006527 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006528 if (!(curproxy->cap & PR_CAP_FE)) {
6529 if (curproxy->logformat_string != default_http_log_format &&
6530 curproxy->logformat_string != default_tcp_log_format &&
6531 curproxy->logformat_string != clf_http_log_format)
6532 free(curproxy->logformat_string);
6533 curproxy->logformat_string = NULL;
6534 }
6535
Willy Tarreau196729e2012-05-31 19:30:26 +02006536 if (curproxy->logformat_string)
Willy Tarreau434c57c2013-01-08 01:10:24 +01006537 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
6538 SMP_VAL_FE_LOG_END);
Willy Tarreau196729e2012-05-31 19:30:26 +02006539
6540 if (curproxy->uniqueid_format_string)
Willy Tarreau434c57c2013-01-08 01:10:24 +01006541 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
6542 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau196729e2012-05-31 19:30:26 +02006543
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544 /* first, we will invert the servers list order */
6545 newsrv = NULL;
6546 while (curproxy->srv) {
6547 struct server *next;
6548
6549 next = curproxy->srv->next;
6550 curproxy->srv->next = newsrv;
6551 newsrv = curproxy->srv;
6552 if (!next)
6553 break;
6554 curproxy->srv = next;
6555 }
6556
Willy Tarreaudd701652010-05-25 23:03:02 +02006557 /* assign automatic UIDs to servers which don't have one yet */
6558 next_id = 1;
6559 newsrv = curproxy->srv;
6560 while (newsrv != NULL) {
6561 if (!newsrv->puid) {
6562 /* server ID not set, use automatic numbering with first
6563 * spare entry starting with next_svid.
6564 */
6565 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6566 newsrv->conf.id.key = newsrv->puid = next_id;
6567 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6568 }
6569 next_id++;
6570 newsrv = newsrv->next;
6571 }
6572
Willy Tarreau20697042007-11-15 23:26:18 +01006573 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006574 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006575
Willy Tarreau62c3be22012-01-20 13:12:32 +01006576 /*
6577 * If this server supports a maxconn parameter, it needs a dedicated
6578 * tasks to fill the emptied slots when a connection leaves.
6579 * Also, resolve deferred tracking dependency if needed.
6580 */
6581 newsrv = curproxy->srv;
6582 while (newsrv != NULL) {
6583 if (newsrv->minconn > newsrv->maxconn) {
6584 /* Only 'minconn' was specified, or it was higher than or equal
6585 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6586 * this will avoid further useless expensive computations.
6587 */
6588 newsrv->maxconn = newsrv->minconn;
6589 } else if (newsrv->maxconn && !newsrv->minconn) {
6590 /* minconn was not specified, so we set it to maxconn */
6591 newsrv->minconn = newsrv->maxconn;
6592 }
6593
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006594#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006595 if (newsrv->use_ssl || newsrv->check.use_ssl)
6596 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006597#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006598
Willy Tarreau62c3be22012-01-20 13:12:32 +01006599 if (newsrv->trackit) {
6600 struct proxy *px;
6601 struct server *srv;
6602 char *pname, *sname;
6603
6604 pname = newsrv->trackit;
6605 sname = strrchr(pname, '/');
6606
6607 if (sname)
6608 *sname++ = '\0';
6609 else {
6610 sname = pname;
6611 pname = NULL;
6612 }
6613
6614 if (pname) {
6615 px = findproxy(pname, PR_CAP_BE);
6616 if (!px) {
6617 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6618 proxy_type_str(curproxy), curproxy->id,
6619 newsrv->id, pname);
6620 cfgerr++;
6621 goto next_srv;
6622 }
6623 } else
6624 px = curproxy;
6625
6626 srv = findserver(px, sname);
6627 if (!srv) {
6628 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6629 proxy_type_str(curproxy), curproxy->id,
6630 newsrv->id, sname);
6631 cfgerr++;
6632 goto next_srv;
6633 }
6634
6635 if (!(srv->state & SRV_CHECKED)) {
6636 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6637 "tracking as it does not have checks enabled.\n",
6638 proxy_type_str(curproxy), curproxy->id,
6639 newsrv->id, px->id, srv->id);
6640 cfgerr++;
6641 goto next_srv;
6642 }
6643
6644 if (curproxy != px &&
6645 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6646 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6647 "tracking: disable-on-404 option inconsistency.\n",
6648 proxy_type_str(curproxy), curproxy->id,
6649 newsrv->id, px->id, srv->id);
6650 cfgerr++;
6651 goto next_srv;
6652 }
6653
6654 /* if the other server is forced disabled, we have to do the same here */
6655 if (srv->state & SRV_MAINTAIN) {
6656 newsrv->state |= SRV_MAINTAIN;
6657 newsrv->state &= ~SRV_RUNNING;
6658 newsrv->health = 0;
6659 }
6660
6661 newsrv->track = srv;
6662 newsrv->tracknext = srv->tracknext;
6663 srv->tracknext = newsrv;
6664
6665 free(newsrv->trackit);
6666 newsrv->trackit = NULL;
6667 }
6668 next_srv:
6669 newsrv = newsrv->next;
6670 }
6671
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006672 /* We have to initialize the server lookup mechanism depending
6673 * on what LB algorithm was choosen.
6674 */
6675
6676 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6677 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6678 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006679 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6680 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6681 init_server_map(curproxy);
6682 } else {
6683 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6684 fwrr_init_server_groups(curproxy);
6685 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006686 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006687
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006688 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006689 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6690 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6691 fwlc_init_server_tree(curproxy);
6692 } else {
6693 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6694 fas_init_server_tree(curproxy);
6695 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006696 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006697
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006698 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006699 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6700 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6701 chash_init_server_tree(curproxy);
6702 } else {
6703 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6704 init_server_map(curproxy);
6705 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006706 break;
6707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006708
6709 if (curproxy->options & PR_O_LOGASAP)
6710 curproxy->to_log &= ~LW_BYTES;
6711
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006712 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006713 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006714 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6715 proxy_type_str(curproxy), curproxy->id);
6716 err_code |= ERR_WARN;
6717 }
6718
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006719 if (curproxy->mode != PR_MODE_HTTP) {
6720 int optnum;
6721
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006722 if (curproxy->uri_auth) {
6723 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6724 proxy_type_str(curproxy), curproxy->id);
6725 err_code |= ERR_WARN;
6726 curproxy->uri_auth = NULL;
6727 }
6728
Willy Tarreau87cf5142011-08-19 22:57:24 +02006729 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006730 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6731 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6732 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006733 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006734 }
6735
6736 if (curproxy->options & PR_O_ORGTO) {
6737 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6738 "originalto", proxy_type_str(curproxy), curproxy->id);
6739 err_code |= ERR_WARN;
6740 curproxy->options &= ~PR_O_ORGTO;
6741 }
6742
6743 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6744 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6745 (curproxy->cap & cfg_opts[optnum].cap) &&
6746 (curproxy->options & cfg_opts[optnum].val)) {
6747 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6748 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6749 err_code |= ERR_WARN;
6750 curproxy->options &= ~cfg_opts[optnum].val;
6751 }
6752 }
6753
6754 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6755 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6756 (curproxy->cap & cfg_opts2[optnum].cap) &&
6757 (curproxy->options2 & cfg_opts2[optnum].val)) {
6758 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6759 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6760 err_code |= ERR_WARN;
6761 curproxy->options2 &= ~cfg_opts2[optnum].val;
6762 }
6763 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006764
Willy Tarreauefa5f512010-03-30 20:13:29 +02006765#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006766 if (curproxy->conn_src.bind_hdr_occ) {
6767 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006768 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006769 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006770 err_code |= ERR_WARN;
6771 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006772#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006773 }
6774
Willy Tarreaubaaee002006-06-26 02:48:02 +02006775 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006776 * ensure that we're not cross-dressing a TCP server into HTTP.
6777 */
6778 newsrv = curproxy->srv;
6779 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006780 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006781 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6782 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006783 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006784 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006785
Willy Tarreau0cec3312011-10-31 13:49:26 +01006786 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6787 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6788 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6789 err_code |= ERR_WARN;
6790 }
6791
Willy Tarreauefa5f512010-03-30 20:13:29 +02006792#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006793 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6794 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006795 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 +01006796 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006797 err_code |= ERR_WARN;
6798 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006799#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006800 newsrv = newsrv->next;
6801 }
6802
Willy Tarreauc1a21672009-08-16 22:37:44 +02006803 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006804 if (!curproxy->accept)
6805 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006806
Willy Tarreauc1a21672009-08-16 22:37:44 +02006807 if (curproxy->tcp_req.inspect_delay ||
6808 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006809 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006810
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006811 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006812 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006813 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006814 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006815
6816 /* both TCP and HTTP must check switching rules */
6817 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6818 }
6819
6820 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006821 if (curproxy->tcp_req.inspect_delay ||
6822 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6823 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6824
Emeric Brun97679e72010-09-23 17:56:44 +02006825 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6826 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6827
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006828 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006829 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006830 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006831 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006832
6833 /* If the backend does requires RDP cookie persistence, we have to
6834 * enable the corresponding analyser.
6835 */
6836 if (curproxy->options2 & PR_O2_RDPC_PRST)
6837 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6838 }
6839
Emeric Brunc52962f2012-11-15 18:28:02 +01006840#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006841 /* Configure SSL for each bind line.
6842 * Note: if configuration fails at some point, the ->ctx member
6843 * remains NULL so that listeners can later detach.
6844 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006845 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006846 if (!bind_conf->is_ssl) {
6847 if (bind_conf->default_ctx) {
6848 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6849 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6850 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006851 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006852 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006853 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006854 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006855 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006856 cfgerr++;
6857 continue;
6858 }
6859
Emeric Brun4b3091e2012-09-24 15:48:52 +02006860 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006861 Alert("Unable to allocate SSL session cache.\n");
6862 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006863 continue;
6864 }
6865
Emeric Brunfc0421f2012-09-07 17:30:07 +02006866 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006867 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006868 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006869#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006870
Willy Tarreaue6b98942007-10-29 01:09:36 +01006871 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006872 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006873 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006874 if (!listener->luid) {
6875 /* listener ID not set, use automatic numbering with first
6876 * spare entry starting with next_luid.
6877 */
6878 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6879 listener->conf.id.key = listener->luid = next_id;
6880 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006881 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006882 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006883
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006884 /* enable separate counters */
6885 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6886 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006887 if (!listener->name)
6888 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006889 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006890
Willy Tarreaue6b98942007-10-29 01:09:36 +01006891 if (curproxy->options & PR_O_TCP_NOLING)
6892 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006893 if (!listener->maxconn)
6894 listener->maxconn = curproxy->maxconn;
6895 if (!listener->backlog)
6896 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006897 if (!listener->maxaccept)
6898 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6899
6900 /* we want to have an optimal behaviour on single process mode to
6901 * maximize the work at once, but in multi-process we want to keep
6902 * some fairness between processes, so we target half of the max
6903 * number of events to be balanced over all the processes the proxy
6904 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6905 * used to disable the limit.
6906 */
6907 if (listener->maxaccept > 0) {
6908 if (nbproc > 1)
6909 listener->maxaccept = (listener->maxaccept + 1) / 2;
6910 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6911 }
6912
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006913 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006914 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006915 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006916 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006917
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006918 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6919 listener->options |= LI_O_TCP_RULES;
6920
Willy Tarreaude3041d2010-05-31 10:56:17 +02006921 if (curproxy->mon_mask.s_addr)
6922 listener->options |= LI_O_CHK_MONNET;
6923
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006924 /* smart accept mode is automatic in HTTP mode */
6925 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006926 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006927 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6928 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006929 }
6930
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006931 /* Release unused SSL configs */
6932 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6933 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006934 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006935#ifdef USE_OPENSSL
6936 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006937 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006938 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006939 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006940 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006941#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006942 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006943
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006944 /* Check multi-process mode compatibility for the current proxy */
6945 if (global.nbproc > 1) {
6946 int nbproc = 0;
6947 if (curproxy->bind_proc) {
6948 int proc;
6949 for (proc = 0; proc < global.nbproc; proc++) {
6950 if (curproxy->bind_proc & (1 << proc)) {
6951 nbproc++;
6952 }
6953 }
6954 } else {
6955 nbproc = global.nbproc;
6956 }
6957 if (curproxy->table.peers.name) {
6958 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6959 curproxy->id);
6960 cfgerr++;
6961 }
6962 if (nbproc > 1) {
6963 if (curproxy->uri_auth) {
6964 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6965 curproxy->id);
6966 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6967 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6968 curproxy->id);
6969 }
6970 }
6971 if (curproxy->appsession_name) {
6972 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6973 curproxy->id);
6974 }
6975 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6976 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6977 curproxy->id);
6978 }
6979 }
6980 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006981
6982 /* create the task associated with the proxy */
6983 curproxy->task = task_new();
6984 if (curproxy->task) {
6985 curproxy->task->context = curproxy;
6986 curproxy->task->process = manage_proxy;
6987 /* no need to queue, it will be done automatically if some
6988 * listener gets limited.
6989 */
6990 curproxy->task->expire = TICK_ETERNITY;
6991 } else {
6992 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6993 curproxy->id);
6994 cfgerr++;
6995 }
6996
Willy Tarreaubaaee002006-06-26 02:48:02 +02006997 curproxy = curproxy->next;
6998 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006999
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007000 /* Check multi-process mode compatibility */
7001 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007002 if (global.stats_fe && !global.stats_fe->bind_proc) {
7003 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 +01007004 }
7005 }
7006
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007007 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7008 struct auth_users *curuser;
7009 int g;
7010
7011 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7012 unsigned int group_mask = 0;
7013 char *group = NULL;
7014
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007015 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007016 continue;
7017
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007018 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007019
7020 for (g = 0; g < curuserlist->grpcnt; g++)
7021 if (!strcmp(curuserlist->groups[g], group))
7022 break;
7023
7024 if (g == curuserlist->grpcnt) {
7025 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7026 curuserlist->name, group, curuser->user);
7027 err_code |= ERR_ALERT | ERR_FATAL;
7028 goto out;
7029 }
7030
7031 group_mask |= (1 << g);
7032 }
7033
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007034 free(curuser->u.groups);
7035 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007036 }
7037
7038 for (g = 0; g < curuserlist->grpcnt; g++) {
7039 char *user = NULL;
7040
7041 if (!curuserlist->groupusers[g])
7042 continue;
7043
7044 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7045 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7046 if (!strcmp(curuser->user, user))
7047 break;
7048
7049 if (!curuser) {
7050 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7051 curuserlist->name, user, curuserlist->groups[g]);
7052 err_code |= ERR_ALERT | ERR_FATAL;
7053 goto out;
7054 }
7055
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007056 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007057 }
7058
7059 free(curuserlist->groupusers[g]);
7060 }
7061
7062 free(curuserlist->groupusers);
7063
7064#ifdef DEBUG_AUTH
7065 for (g = 0; g < curuserlist->grpcnt; g++) {
7066 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7067
7068 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007069 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007070 fprintf(stderr, " %s", curuser->user);
7071 }
7072
7073 fprintf(stderr, "\n");
7074 }
7075#endif
7076
Willy Tarreaufbb78422011-06-05 15:38:35 +02007077 }
7078
7079 /* automatically compute fullconn if not set. We must not do it in the
7080 * loop above because cross-references are not yet fully resolved.
7081 */
7082 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7083 /* If <fullconn> is not set, let's set it to 10% of the sum of
7084 * the possible incoming frontend's maxconns.
7085 */
7086 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7087 struct proxy *fe;
7088 int total = 0;
7089
7090 /* sum up the number of maxconns of frontends which
7091 * reference this backend at least once or which are
7092 * the same one ('listen').
7093 */
7094 for (fe = proxy; fe; fe = fe->next) {
7095 struct switching_rule *rule;
7096 struct hdr_exp *exp;
7097 int found = 0;
7098
7099 if (!(fe->cap & PR_CAP_FE))
7100 continue;
7101
7102 if (fe == curproxy) /* we're on a "listen" instance */
7103 found = 1;
7104
7105 if (fe->defbe.be == curproxy) /* "default_backend" */
7106 found = 1;
7107
7108 /* check if a "use_backend" rule matches */
7109 if (!found) {
7110 list_for_each_entry(rule, &fe->switching_rules, list) {
7111 if (rule->be.backend == curproxy) {
7112 found = 1;
7113 break;
7114 }
7115 }
7116 }
7117
7118 /* check if a "reqsetbe" rule matches */
7119 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7120 if (exp->action == ACT_SETBE &&
7121 (struct proxy *)exp->replace == curproxy) {
7122 found = 1;
7123 break;
7124 }
7125 }
7126
7127 /* now we've checked all possible ways to reference a backend
7128 * from a frontend.
7129 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007130 if (!found)
7131 continue;
7132 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007133 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007134 /* we have the sum of the maxconns in <total>. We only
7135 * keep 10% of that sum to set the default fullconn, with
7136 * a hard minimum of 1 (to avoid a divide by zero).
7137 */
7138 curproxy->fullconn = (total + 9) / 10;
7139 if (!curproxy->fullconn)
7140 curproxy->fullconn = 1;
7141 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007142 }
7143
Willy Tarreau056f5682010-06-06 15:51:11 +02007144 /* initialize stick-tables on backend capable proxies. This must not
7145 * be done earlier because the data size may be discovered while parsing
7146 * other proxies.
7147 */
7148 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007149 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007150
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007151 /*
7152 * Recount currently required checks.
7153 */
7154
7155 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7156 int optnum;
7157
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007158 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7159 if (curproxy->options & cfg_opts[optnum].val)
7160 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007161
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007162 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7163 if (curproxy->options2 & cfg_opts2[optnum].val)
7164 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007165 }
7166
Willy Tarreau122541c2011-09-07 21:24:49 +02007167 if (peers) {
7168 struct peers *curpeers = peers, **last;
7169 struct peer *p, *pb;
7170
7171 /* Remove all peers sections which don't have a valid listener.
7172 * This can happen when a peers section is never referenced and
7173 * does not contain a local peer.
7174 */
7175 last = &peers;
7176 while (*last) {
7177 curpeers = *last;
7178 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007179 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007180 last = &curpeers->next;
7181 continue;
7182 }
7183
7184 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7185 curpeers->id, localpeer);
7186
7187 p = curpeers->remote;
7188 while (p) {
7189 pb = p->next;
7190 free(p->id);
7191 free(p);
7192 p = pb;
7193 }
7194
7195 /* Destroy and unlink this curpeers section.
7196 * Note: curpeers is backed up into *last.
7197 */
7198 free(curpeers->id);
7199 curpeers = curpeers->next;
7200 free(*last);
7201 *last = curpeers;
7202 }
7203 }
7204
Willy Tarreau34eb6712011-10-24 18:15:04 +02007205 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007206 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007207 MEM_F_SHARED);
7208
Willy Tarreaubb925012009-07-23 13:36:36 +02007209 if (cfgerr > 0)
7210 err_code |= ERR_ALERT | ERR_FATAL;
7211 out:
7212 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007213}
7214
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007215/*
7216 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7217 * parsing sessions.
7218 */
7219void cfg_register_keywords(struct cfg_kw_list *kwl)
7220{
7221 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7222}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007223
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007224/*
7225 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7226 */
7227void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7228{
7229 LIST_DEL(&kwl->list);
7230 LIST_INIT(&kwl->list);
7231}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007232
7233/*
7234 * Local variables:
7235 * c-indent-level: 8
7236 * c-basic-offset: 8
7237 * End:
7238 */