blob: 73a08a42a185729610702a18c339ca3c276a5c56 [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
Simon Horman66183002013-02-23 10:16:43 +09001325 defproxy.defsrv.check.inter = DEF_CHKINTR;
1326 defproxy.defsrv.check.fastinter = 0;
1327 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001328 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1329 defproxy.defsrv.agent.fastinter = 0;
1330 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001331 defproxy.defsrv.check.rise = DEF_RISETIME;
1332 defproxy.defsrv.check.fall = DEF_FALLTIME;
1333 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1334 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001335 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001336 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001337 defproxy.defsrv.maxqueue = 0;
1338 defproxy.defsrv.minconn = 0;
1339 defproxy.defsrv.maxconn = 0;
1340 defproxy.defsrv.slowstart = 0;
1341 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1342 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1343 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344}
1345
Willy Tarreauade5ec42010-01-28 19:33:49 +01001346
1347static int create_cond_regex_rule(const char *file, int line,
1348 struct proxy *px, int dir, int action, int flags,
1349 const char *cmd, const char *reg, const char *repl,
1350 const char **cond_start)
1351{
1352 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001353 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001354 const char *err;
1355 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001356 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001357
1358 if (px == &defproxy) {
1359 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (*reg == 0) {
1365 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto err;
1368 }
1369
1370 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1371 err_code |= ERR_WARN;
1372
Willy Tarreau5321c422010-01-28 20:35:13 +01001373 if (cond_start &&
1374 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001375 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1376 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1377 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001378 err_code |= ERR_ALERT | ERR_FATAL;
1379 goto err;
1380 }
1381 }
1382 else if (cond_start && **cond_start) {
1383 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1384 file, line, cmd, *cond_start);
1385 err_code |= ERR_ALERT | ERR_FATAL;
1386 goto err;
1387 }
1388
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001389 err_code |= warnif_cond_conflicts(cond,
1390 (dir == SMP_OPT_DIR_REQ) ?
1391 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1392 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1393 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001394
Willy Tarreauade5ec42010-01-28 19:33:49 +01001395 preg = calloc(1, sizeof(regex_t));
1396 if (!preg) {
1397 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1398 err_code = ERR_ALERT | ERR_FATAL;
1399 goto err;
1400 }
1401
1402 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1403 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1404 err_code = ERR_ALERT | ERR_FATAL;
1405 goto err;
1406 }
1407
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001408 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001409 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001410 if (repl && err) {
1411 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1412 file, line, cmd, *err);
1413 err_code |= ERR_ALERT | ERR_FATAL;
1414 goto err;
1415 }
1416
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001417 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001418 err_code |= ERR_WARN;
1419
Willy Tarreauf4068b62012-05-08 17:37:49 +02001420 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001421 return err_code;
1422 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001423 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001424 free(preg);
1425 return err_code;
1426}
1427
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001429 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001430 * Returns the error code, 0 if OK, or any combination of :
1431 * - ERR_ABORT: must abort ASAP
1432 * - ERR_FATAL: we can continue parsing but not start the service
1433 * - ERR_WARN: a warning has been emitted
1434 * - ERR_ALERT: an alert has been emitted
1435 * Only the two first ones can stop processing, the two others are just
1436 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001438int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1439{
1440 static struct peers *curpeers = NULL;
1441 struct peer *newpeer = NULL;
1442 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001443 struct bind_conf *bind_conf;
1444 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001445 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001446 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001447
1448 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001449 if (!*args[1]) {
1450 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1451 err_code |= ERR_ALERT | ERR_FATAL;
1452 goto out;
1453 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001454
1455 err = invalid_char(args[1]);
1456 if (err) {
1457 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1458 file, linenum, *err, args[0], args[1]);
1459 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001460 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001461 }
1462
1463 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1464 /*
1465 * If there are two proxies with the same name only following
1466 * combinations are allowed:
1467 */
1468 if (strcmp(curpeers->id, args[1]) == 0) {
1469 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1470 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1471 err_code |= ERR_WARN;
1472 }
1473 }
1474
1475 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1476 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1477 err_code |= ERR_ALERT | ERR_ABORT;
1478 goto out;
1479 }
1480
1481 curpeers->next = peers;
1482 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001483 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001484 curpeers->conf.line = linenum;
1485 curpeers->last_change = now.tv_sec;
1486 curpeers->id = strdup(args[1]);
1487 }
1488 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001489 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001490 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001491 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001492
1493 if (!*args[2]) {
1494 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1495 file, linenum, args[0]);
1496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto out;
1498 }
1499
1500 err = invalid_char(args[1]);
1501 if (err) {
1502 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1503 file, linenum, *err, args[1]);
1504 err_code |= ERR_ALERT | ERR_FATAL;
1505 goto out;
1506 }
1507
1508 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1509 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1510 err_code |= ERR_ALERT | ERR_ABORT;
1511 goto out;
1512 }
1513
1514 /* the peers are linked backwards first */
1515 curpeers->count++;
1516 newpeer->next = curpeers->remote;
1517 curpeers->remote = newpeer;
1518 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001519 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001520 newpeer->conf.line = linenum;
1521
1522 newpeer->last_change = now.tv_sec;
1523 newpeer->id = strdup(args[1]);
1524
Willy Tarreau902636f2013-03-10 19:44:48 +01001525 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001526 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001527 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001530 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001531
1532 proto = protocol_by_family(sk->ss_family);
1533 if (!proto || !proto->connect) {
1534 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1535 file, linenum, args[0], args[1]);
1536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001539
1540 if (port1 != port2) {
1541 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1542 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
1545 }
1546
Willy Tarreau2aa38802013-02-20 19:20:59 +01001547 if (!port1) {
1548 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1549 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001550 err_code |= ERR_ALERT | ERR_FATAL;
1551 goto out;
1552 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001553
Emeric Brun32da3c42010-09-23 18:39:19 +02001554 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001555 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001556 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001557 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001558
Emeric Brun32da3c42010-09-23 18:39:19 +02001559 if (strcmp(newpeer->id, localpeer) == 0) {
1560 /* Current is local peer, it define a frontend */
1561 newpeer->local = 1;
1562
1563 if (!curpeers->peers_fe) {
1564 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1565 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1566 err_code |= ERR_ALERT | ERR_ABORT;
1567 goto out;
1568 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001569
Willy Tarreau237250c2011-07-29 01:49:03 +02001570 init_new_proxy(curpeers->peers_fe);
1571 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001572
1573 curpeers->peers_fe->last_change = now.tv_sec;
1574 curpeers->peers_fe->id = strdup(args[1]);
1575 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001576 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001577 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1578 curpeers->peers_fe->timeout.connect = 5000;
1579 curpeers->peers_fe->accept = peer_accept;
1580 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001581 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1582 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001583
1584 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1585
Willy Tarreau902636f2013-03-10 19:44:48 +01001586 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1587 if (errmsg && *errmsg) {
1588 indent_msg(&errmsg, 2);
1589 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001590 }
1591 else
1592 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1593 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001594 err_code |= ERR_FATAL;
1595 goto out;
1596 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001597
1598 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1599 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1600 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1601 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1602 l->accept = session_accept;
1603 l->handler = process_session;
1604 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1605 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1606 global.maxsock += l->maxconn;
1607 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001608 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001609 else {
1610 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1611 file, linenum, args[0], args[1],
1612 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1613 err_code |= ERR_FATAL;
1614 goto out;
1615 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001616 }
1617 } /* neither "peer" nor "peers" */
1618 else if (*args[0] != 0) {
1619 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
1622 }
1623
1624out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001625 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001626 return err_code;
1627}
1628
Simon Horman69d29f92013-02-23 15:14:19 +09001629static int init_check(struct check *check, int type, const char * file, int linenum)
1630{
1631 check->type = type;
1632
1633 /* Allocate buffer for requests... */
1634 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1635 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1636 return ERR_ALERT | ERR_ABORT;
1637 }
1638 check->bi->size = global.tune.chksize;
1639
1640 /* Allocate buffer for responses... */
1641 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1642 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1643 return ERR_ALERT | ERR_ABORT;
1644 }
1645 check->bo->size = global.tune.chksize;
1646
1647 /* Allocate buffer for partial results... */
1648 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1649 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1650 return ERR_ALERT | ERR_ABORT;
1651 }
1652
1653 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1654
1655 return 0;
1656}
Emeric Brun32da3c42010-09-23 18:39:19 +02001657
Willy Tarreau3842f002009-06-14 11:39:52 +02001658int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659{
1660 static struct proxy *curproxy = NULL;
1661 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001662 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001663 int rc;
1664 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001665 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001666 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001667 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001668 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001669 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670
Willy Tarreau977b8e42006-12-29 14:19:17 +01001671 if (!strcmp(args[0], "listen"))
1672 rc = PR_CAP_LISTEN;
1673 else if (!strcmp(args[0], "frontend"))
1674 rc = PR_CAP_FE | PR_CAP_RS;
1675 else if (!strcmp(args[0], "backend"))
1676 rc = PR_CAP_BE | PR_CAP_RS;
1677 else if (!strcmp(args[0], "ruleset"))
1678 rc = PR_CAP_RS;
1679 else
1680 rc = PR_CAP_NONE;
1681
1682 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 if (!*args[1]) {
1684 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1685 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1686 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001687 err_code |= ERR_ALERT | ERR_ABORT;
1688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001689 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001690
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001691 err = invalid_char(args[1]);
1692 if (err) {
1693 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1694 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001696 }
1697
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001698 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1699 /*
1700 * If there are two proxies with the same name only following
1701 * combinations are allowed:
1702 *
1703 * listen backend frontend ruleset
1704 * listen - - - -
1705 * backend - - OK -
1706 * frontend - OK - -
1707 * ruleset - - - -
1708 */
1709
1710 if (!strcmp(curproxy->id, args[1]) &&
1711 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1712 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001713 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1714 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1715 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001717 }
1718 }
1719
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1721 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001722 err_code |= ERR_ALERT | ERR_ABORT;
1723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001725
Willy Tarreau97cb7802010-01-03 20:23:58 +01001726 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 curproxy->next = proxy;
1728 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001729 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1730 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001731 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001733 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734
1735 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001736 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001737 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001738
Willy Tarreau4348fad2012-09-20 16:48:07 +02001739 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1740
Willy Tarreau902636f2013-03-10 19:44:48 +01001741 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1742 if (errmsg && *errmsg) {
1743 indent_msg(&errmsg, 2);
1744 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001745 }
1746 else
1747 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1748 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001749 err_code |= ERR_FATAL;
1750 goto out;
1751 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001752
Willy Tarreau4348fad2012-09-20 16:48:07 +02001753 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001754 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756 }
1757
1758 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001759 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001760 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001761
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001764 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001765 curproxy->no_options = defproxy.no_options;
1766 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001767 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001768 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001769 curproxy->except_net = defproxy.except_net;
1770 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001771 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001772 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001774 if (defproxy.fwdfor_hdr_len) {
1775 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1776 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1777 }
1778
Willy Tarreaub86db342009-11-30 11:50:16 +01001779 if (defproxy.orgto_hdr_len) {
1780 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1781 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1782 }
1783
Mark Lamourinec2247f02012-01-04 13:02:01 -05001784 if (defproxy.server_id_hdr_len) {
1785 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1786 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1787 }
1788
Willy Tarreau977b8e42006-12-29 14:19:17 +01001789 if (curproxy->cap & PR_CAP_FE) {
1790 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001791 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001792 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793
1794 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001795 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1796 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001797
1798 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800
Willy Tarreau977b8e42006-12-29 14:19:17 +01001801 if (curproxy->cap & PR_CAP_BE) {
1802 curproxy->fullconn = defproxy.fullconn;
1803 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001805 if (defproxy.check_req) {
1806 curproxy->check_req = calloc(1, defproxy.check_len);
1807 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1808 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001809 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001811 if (defproxy.expect_str) {
1812 curproxy->expect_str = strdup(defproxy.expect_str);
1813 if (defproxy.expect_regex) {
1814 /* note: this regex is known to be valid */
1815 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1816 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1817 }
1818 }
1819
Willy Tarreau67402132012-05-31 20:40:20 +02001820 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001821 if (defproxy.cookie_name)
1822 curproxy->cookie_name = strdup(defproxy.cookie_name);
1823 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001824 if (defproxy.cookie_domain)
1825 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001826
Willy Tarreau31936852010-10-06 16:59:56 +02001827 if (defproxy.cookie_maxidle)
1828 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1829
1830 if (defproxy.cookie_maxlife)
1831 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1832
Emeric Brun647caf12009-06-30 17:57:00 +02001833 if (defproxy.rdp_cookie_name)
1834 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1835 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1836
Willy Tarreau01732802007-11-01 22:48:15 +01001837 if (defproxy.url_param_name)
1838 curproxy->url_param_name = strdup(defproxy.url_param_name);
1839 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001840
Benoitaffb4812009-03-25 13:02:10 +01001841 if (defproxy.hh_name)
1842 curproxy->hh_name = strdup(defproxy.hh_name);
1843 curproxy->hh_len = defproxy.hh_len;
1844 curproxy->hh_match_domain = defproxy.hh_match_domain;
1845
Willy Tarreauef9a3602012-12-08 22:29:20 +01001846 if (defproxy.conn_src.iface_name)
1847 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1848 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001849 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001850#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001851 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001852#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001855 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001856 if (defproxy.capture_name)
1857 curproxy->capture_name = strdup(defproxy.capture_name);
1858 curproxy->capture_namelen = defproxy.capture_namelen;
1859 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861
Willy Tarreau977b8e42006-12-29 14:19:17 +01001862 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001863 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001864 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001865 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001866 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001867 curproxy->uri_auth = defproxy.uri_auth;
1868 curproxy->mon_net = defproxy.mon_net;
1869 curproxy->mon_mask = defproxy.mon_mask;
1870 if (defproxy.monitor_uri)
1871 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1872 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001873 if (defproxy.defbe.name)
1874 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001875
1876 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001877 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1878 if (curproxy->conf.logformat_string &&
1879 curproxy->conf.logformat_string != default_http_log_format &&
1880 curproxy->conf.logformat_string != default_tcp_log_format &&
1881 curproxy->conf.logformat_string != clf_http_log_format)
1882 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1883
1884 if (defproxy.conf.lfs_file) {
1885 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1886 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1887 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001888 }
1889
1890 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001891 curproxy->timeout.connect = defproxy.timeout.connect;
1892 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001893 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001894 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001895 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001896 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001897 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001898 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001899 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001900 }
1901
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001903
1904 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001905 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001906 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001907 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001908 LIST_INIT(&node->list);
1909 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1910 }
1911
Willy Tarreau62a61232013-04-12 18:13:46 +02001912 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1913 if (curproxy->conf.uniqueid_format_string)
1914 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1915
1916 if (defproxy.conf.uif_file) {
1917 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1918 curproxy->conf.uif_line = defproxy.conf.uif_line;
1919 }
William Lallemanda73203e2012-03-12 12:48:57 +01001920
1921 /* copy default header unique id */
1922 if (defproxy.header_unique_id)
1923 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1924
William Lallemand82fe75c2012-10-23 10:25:10 +02001925 /* default compression options */
1926 if (defproxy.comp != NULL) {
1927 curproxy->comp = calloc(1, sizeof(struct comp));
1928 curproxy->comp->algos = defproxy.comp->algos;
1929 curproxy->comp->types = defproxy.comp->types;
1930 }
1931
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001933 curproxy->conf.used_listener_id = EB_ROOT;
1934 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001935
Willy Tarreau93893792009-07-23 13:19:11 +02001936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 }
1938 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1939 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001940 /* FIXME-20070101: we should do this too at the end of the
1941 * config parsing to free all default values.
1942 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001943 free(defproxy.check_req);
1944 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001945 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001946 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001947 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001948 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001949 free(defproxy.capture_name);
1950 free(defproxy.monitor_uri);
1951 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001952 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001953 free(defproxy.fwdfor_hdr_name);
1954 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001955 free(defproxy.orgto_hdr_name);
1956 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001957 free(defproxy.server_id_hdr_name);
1958 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001959 free(defproxy.expect_str);
1960 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001961
Willy Tarreau62a61232013-04-12 18:13:46 +02001962 if (defproxy.conf.logformat_string != default_http_log_format &&
1963 defproxy.conf.logformat_string != default_tcp_log_format &&
1964 defproxy.conf.logformat_string != clf_http_log_format)
1965 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001966
Willy Tarreau62a61232013-04-12 18:13:46 +02001967 free(defproxy.conf.uniqueid_format_string);
1968 free(defproxy.conf.lfs_file);
1969 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001970
Willy Tarreaua534fea2008-08-03 12:19:50 +02001971 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001972 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001973
Willy Tarreaubaaee002006-06-26 02:48:02 +02001974 /* we cannot free uri_auth because it might already be used */
1975 init_default_instance();
1976 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001977 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1978 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001979 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 }
1982 else if (curproxy == NULL) {
1983 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001987
1988 /* update the current file and line being parsed */
1989 curproxy->conf.args.file = curproxy->conf.file;
1990 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001991
1992 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001994 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001995 int cur_arg;
1996
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 if (curproxy == &defproxy) {
1998 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004
Willy Tarreau24709282013-03-10 21:32:12 +01002005 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002006 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002008 err_code |= ERR_ALERT | ERR_FATAL;
2009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002010 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002011
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002012 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002013
2014 /* use default settings for unix sockets */
2015 bind_conf->ux.uid = global.unix_bind.ux.uid;
2016 bind_conf->ux.gid = global.unix_bind.ux.gid;
2017 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002018
2019 /* NOTE: the following line might create several listeners if there
2020 * are comma-separated IPs or port ranges. So all further processing
2021 * will have to be applied to all listeners created after last_listen.
2022 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002023 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2024 if (errmsg && *errmsg) {
2025 indent_msg(&errmsg, 2);
2026 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002027 }
2028 else
2029 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2030 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
2033 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002034
Willy Tarreau4348fad2012-09-20 16:48:07 +02002035 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2036 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002037 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002038 }
2039
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002040 cur_arg = 2;
2041 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002042 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002043 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002044 char *err;
2045
Willy Tarreau26982662012-09-12 23:17:10 +02002046 kw = bind_find_kw(args[cur_arg]);
2047 if (kw) {
2048 char *err = NULL;
2049 int code;
2050
2051 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002052 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2053 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002054 cur_arg += 1 + kw->skip ;
2055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
2057 }
2058
Willy Tarreau4348fad2012-09-20 16:48:07 +02002059 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002060 err_code |= code;
2061
2062 if (code) {
2063 if (err && *err) {
2064 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002065 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002066 }
2067 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002068 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2069 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002070 if (code & ERR_FATAL) {
2071 free(err);
2072 cur_arg += 1 + kw->skip;
2073 goto out;
2074 }
2075 }
2076 free(err);
2077 cur_arg += 1 + kw->skip;
2078 continue;
2079 }
2080
Willy Tarreau8638f482012-09-18 18:01:17 +02002081 err = NULL;
2082 if (!bind_dumped) {
2083 bind_dump_kws(&err);
2084 indent_msg(&err, 4);
2085 bind_dumped = 1;
2086 }
2087
2088 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2089 file, linenum, args[0], args[1], args[cur_arg],
2090 err ? " Registered keywords :" : "", err ? err : "");
2091 free(err);
2092
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002095 }
Willy Tarreau93893792009-07-23 13:19:11 +02002096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 }
2098 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2099 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2100 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002106 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002107
Willy Tarreaubaaee002006-06-26 02:48:02 +02002108 /* flush useless bits */
2109 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002112 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002113 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115
Willy Tarreau1c47f852006-07-09 08:22:27 +02002116 if (!*args[1]) {
2117 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2118 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002119 err_code |= ERR_ALERT | ERR_FATAL;
2120 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002121 }
2122
Willy Tarreaua534fea2008-08-03 12:19:50 +02002123 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002124 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002125 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002126 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002127 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2128
Willy Tarreau93893792009-07-23 13:19:11 +02002129 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2132 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2133 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2134 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2135 else {
2136 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_ALERT | ERR_FATAL;
2138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139 }
2140 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002141 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002142 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002143
2144 if (curproxy == &defproxy) {
2145 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2146 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002147 err_code |= ERR_ALERT | ERR_FATAL;
2148 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002149 }
2150
2151 if (!*args[1]) {
2152 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002156 }
2157
2158 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002159 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002160
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002161 if (curproxy->uuid <= 0) {
2162 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002163 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002166 }
2167
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002168 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2169 if (node) {
2170 struct proxy *target = container_of(node, struct proxy, conf.id);
2171 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2172 file, linenum, proxy_type_str(curproxy), curproxy->id,
2173 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
2176 }
2177 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002178 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002179 else if (!strcmp(args[0], "description")) {
2180 int i, len=0;
2181 char *d;
2182
Cyril Bonté99ed3272010-01-24 23:29:44 +01002183 if (curproxy == &defproxy) {
2184 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2185 file, linenum, args[0]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002190 if (!*args[1]) {
2191 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2192 file, linenum, args[0]);
2193 return -1;
2194 }
2195
2196 for(i=1; *args[i]; i++)
2197 len += strlen(args[i])+1;
2198
2199 d = (char *)calloc(1, len);
2200 curproxy->desc = d;
2201
2202 d += sprintf(d, "%s", args[1]);
2203 for(i=2; *args[i]; i++)
2204 d += sprintf(d, " %s", args[i]);
2205
2206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2208 curproxy->state = PR_STSTOPPED;
2209 }
2210 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2211 curproxy->state = PR_STNEW;
2212 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002213 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2214 int cur_arg = 1;
2215 unsigned int set = 0;
2216
2217 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002218 unsigned int low, high;
2219
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002220 if (strcmp(args[cur_arg], "all") == 0) {
2221 set = 0;
2222 break;
2223 }
2224 else if (strcmp(args[cur_arg], "odd") == 0) {
2225 set |= 0x55555555;
2226 }
2227 else if (strcmp(args[cur_arg], "even") == 0) {
2228 set |= 0xAAAAAAAA;
2229 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002230 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002231 char *dash = strchr(args[cur_arg], '-');
2232
2233 low = high = str2uic(args[cur_arg]);
2234 if (dash)
2235 high = str2uic(dash + 1);
2236
2237 if (high < low) {
2238 unsigned int swap = low;
2239 low = high;
2240 high = swap;
2241 }
2242
2243 if (low < 1 || high > 32) {
2244 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002248 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002249
2250 if (high > global.nbproc) {
2251 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2252 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002254 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002255 while (low <= high)
2256 set |= 1 << (low++ - 1);
2257 }
2258 else {
2259 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2260 file, linenum, args[0]);
2261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002263 }
2264 cur_arg++;
2265 }
2266 curproxy->bind_proc = set;
2267 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002268 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002269 if (curproxy == &defproxy) {
2270 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002273 }
2274
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002275 err = invalid_char(args[1]);
2276 if (err) {
2277 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2278 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002280 }
2281
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002282 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002283 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2284 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002287 }
2288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002289 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2290 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291
Willy Tarreau977b8e42006-12-29 14:19:17 +01002292 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002294
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 if (*(args[1]) == 0) {
2296 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002301
Willy Tarreau67402132012-05-31 20:40:20 +02002302 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002303 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002304 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002305 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 curproxy->cookie_name = strdup(args[1]);
2307 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002308
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 cur_arg = 2;
2310 while (*(args[cur_arg])) {
2311 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002312 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 }
2314 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002315 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 }
2317 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002318 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 }
2320 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002321 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 }
2323 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002324 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002325 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002326 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002327 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002330 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002332 else if (!strcmp(args[cur_arg], "httponly")) {
2333 curproxy->ck_opts |= PR_CK_HTTPONLY;
2334 }
2335 else if (!strcmp(args[cur_arg], "secure")) {
2336 curproxy->ck_opts |= PR_CK_SECURE;
2337 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002338 else if (!strcmp(args[cur_arg], "domain")) {
2339 if (!*args[cur_arg + 1]) {
2340 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2341 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002344 }
2345
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002346 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002347 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002348 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2349 " dots nor does not start with a dot."
2350 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002351 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002352 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002353 }
2354
2355 err = invalid_domainchar(args[cur_arg + 1]);
2356 if (err) {
2357 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2358 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002361 }
2362
Willy Tarreau68a897b2009-12-03 23:28:34 +01002363 if (!curproxy->cookie_domain) {
2364 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2365 } else {
2366 /* one domain was already specified, add another one by
2367 * building the string which will be returned along with
2368 * the cookie.
2369 */
2370 char *new_ptr;
2371 int new_len = strlen(curproxy->cookie_domain) +
2372 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2373 new_ptr = malloc(new_len);
2374 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2375 free(curproxy->cookie_domain);
2376 curproxy->cookie_domain = new_ptr;
2377 }
Willy Tarreau31936852010-10-06 16:59:56 +02002378 cur_arg++;
2379 }
2380 else if (!strcmp(args[cur_arg], "maxidle")) {
2381 unsigned int maxidle;
2382 const char *res;
2383
2384 if (!*args[cur_arg + 1]) {
2385 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2386 file, linenum, args[cur_arg]);
2387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
2389 }
2390
2391 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2392 if (res) {
2393 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2394 file, linenum, *res, args[cur_arg]);
2395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
2397 }
2398 curproxy->cookie_maxidle = maxidle;
2399 cur_arg++;
2400 }
2401 else if (!strcmp(args[cur_arg], "maxlife")) {
2402 unsigned int maxlife;
2403 const char *res;
2404
2405 if (!*args[cur_arg + 1]) {
2406 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2407 file, linenum, args[cur_arg]);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
2410 }
2411
2412 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2413 if (res) {
2414 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2415 file, linenum, *res, args[cur_arg]);
2416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
2418 }
2419 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002420 cur_arg++;
2421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002423 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 +02002424 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 }
2428 cur_arg++;
2429 }
Willy Tarreau67402132012-05-31 20:40:20 +02002430 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2432 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
2435
Willy Tarreau67402132012-05-31 20:40:20 +02002436 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2438 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002441
Willy Tarreau67402132012-05-31 20:40:20 +02002442 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002443 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2444 file, linenum);
2445 err_code |= ERR_ALERT | ERR_FATAL;
2446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002448 else if (!strcmp(args[0], "persist")) { /* persist */
2449 if (*(args[1]) == 0) {
2450 Alert("parsing [%s:%d] : missing persist method.\n",
2451 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002454 }
2455
2456 if (!strncmp(args[1], "rdp-cookie", 10)) {
2457 curproxy->options2 |= PR_O2_RDPC_PRST;
2458
Emeric Brunb982a3d2010-01-04 15:45:53 +01002459 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002460 const char *beg, *end;
2461
2462 beg = args[1] + 11;
2463 end = strchr(beg, ')');
2464
2465 if (!end || end == beg) {
2466 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2467 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002470 }
2471
2472 free(curproxy->rdp_cookie_name);
2473 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2474 curproxy->rdp_cookie_len = end-beg;
2475 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002476 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002477 free(curproxy->rdp_cookie_name);
2478 curproxy->rdp_cookie_name = strdup("msts");
2479 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2480 }
2481 else { /* syntax */
2482 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2483 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002486 }
2487 }
2488 else {
2489 Alert("parsing [%s:%d] : unknown persist method.\n",
2490 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002493 }
2494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002496 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002498 if (curproxy == &defproxy) {
2499 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
2502 }
2503
Willy Tarreau977b8e42006-12-29 14:19:17 +01002504 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002506
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002508 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002509 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }
2513 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002514 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 curproxy->appsession_name = strdup(args[1]);
2516 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2517 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002518 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2519 if (err) {
2520 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2521 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002524 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002525 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002526
Willy Tarreau51041c72007-09-09 21:56:53 +02002527 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2528 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_ABORT;
2530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002532
2533 cur_arg = 6;
2534 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002535 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2536 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002537 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002538 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002539 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002540 } else if (!strcmp(args[cur_arg], "prefix")) {
2541 curproxy->options2 |= PR_O2_AS_PFX;
2542 } else if (!strcmp(args[cur_arg], "mode")) {
2543 if (!*args[cur_arg + 1]) {
2544 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2545 file, linenum, args[0], args[cur_arg]);
2546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
2548 }
2549
2550 cur_arg++;
2551 if (!strcmp(args[cur_arg], "query-string")) {
2552 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2553 curproxy->options2 |= PR_O2_AS_M_QS;
2554 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2555 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2556 curproxy->options2 |= PR_O2_AS_M_PP;
2557 } else {
2558 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
2561 }
2562 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002563 cur_arg++;
2564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 } /* Url App Session */
2566 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002567 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002571 if (curproxy == &defproxy) {
2572 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
2575 }
2576
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 if (*(args[4]) == 0) {
2578 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2579 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002583 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 curproxy->capture_name = strdup(args[2]);
2585 curproxy->capture_namelen = strlen(curproxy->capture_name);
2586 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 curproxy->to_log |= LW_COOKIE;
2588 }
2589 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2590 struct cap_hdr *hdr;
2591
2592 if (curproxy == &defproxy) {
2593 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 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
2597
2598 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2599 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2600 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002601 err_code |= ERR_ALERT | ERR_FATAL;
2602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 }
2604
2605 hdr = calloc(sizeof(struct cap_hdr), 1);
2606 hdr->next = curproxy->req_cap;
2607 hdr->name = strdup(args[3]);
2608 hdr->namelen = strlen(args[3]);
2609 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002610 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 hdr->index = curproxy->nb_req_cap++;
2612 curproxy->req_cap = hdr;
2613 curproxy->to_log |= LW_REQHDR;
2614 }
2615 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2616 struct cap_hdr *hdr;
2617
2618 if (curproxy == &defproxy) {
2619 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 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
2623
2624 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2625 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2626 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 }
2630 hdr = calloc(sizeof(struct cap_hdr), 1);
2631 hdr->next = curproxy->rsp_cap;
2632 hdr->name = strdup(args[3]);
2633 hdr->namelen = strlen(args[3]);
2634 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002635 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 hdr->index = curproxy->nb_rsp_cap++;
2637 curproxy->rsp_cap = hdr;
2638 curproxy->to_log |= LW_RSPHDR;
2639 }
2640 else {
2641 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2642 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 }
2646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002648 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002649 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002650
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 if (*(args[1]) == 0) {
2652 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 }
2657 curproxy->conn_retries = atol(args[1]);
2658 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002659 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002660 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002661
2662 if (curproxy == &defproxy) {
2663 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
Willy Tarreau20b0de52012-12-24 15:45:22 +01002668 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2669 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2670 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2671 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002672 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002673 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2674 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 +01002675 file, linenum, args[0]);
2676 err_code |= ERR_WARN;
2677 }
2678
Willy Tarreauff011f22011-01-06 17:51:27 +01002679 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002680
Willy Tarreauff011f22011-01-06 17:51:27 +01002681 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002682 err_code |= ERR_ALERT | ERR_ABORT;
2683 goto out;
2684 }
2685
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002686 err_code |= warnif_cond_conflicts(rule->cond,
2687 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2688 file, linenum);
2689
Willy Tarreauff011f22011-01-06 17:51:27 +01002690 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002691 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002692 else if (!strcmp(args[0], "http-response")) { /* response access control */
2693 struct http_res_rule *rule;
2694
2695 if (curproxy == &defproxy) {
2696 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700
2701 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2702 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2703 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2704 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2705 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2706 file, linenum, args[0]);
2707 err_code |= ERR_WARN;
2708 }
2709
2710 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2711
2712 if (!rule) {
2713 err_code |= ERR_ALERT | ERR_ABORT;
2714 goto out;
2715 }
2716
2717 err_code |= warnif_cond_conflicts(rule->cond,
2718 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2719 file, linenum);
2720
2721 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2722 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002723 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2724 /* set the header name and length into the proxy structure */
2725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2726 err_code |= ERR_WARN;
2727
2728 if (!*args[1]) {
2729 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2730 file, linenum, args[0]);
2731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
2733 }
2734
2735 /* set the desired header name */
2736 free(curproxy->server_id_hdr_name);
2737 curproxy->server_id_hdr_name = strdup(args[1]);
2738 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2739 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002740 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002741 if (curproxy == &defproxy) {
2742 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002745 }
2746
Willy Tarreauef6494c2010-01-28 17:12:36 +01002747 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002748 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2749 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002752 }
2753
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002754 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2755 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2756 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002759 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002760
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002761 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002762 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002763 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002764 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002765 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002766
Cyril Bonté99ed3272010-01-24 23:29:44 +01002767 if (curproxy == &defproxy) {
2768 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
2772
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002773 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002774 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2775 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002778 }
2779
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002780 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002781 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002782 err_code |= warnif_cond_conflicts(rule->cond,
2783 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2784 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002785 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002786 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002787 struct switching_rule *rule;
2788
Willy Tarreaub099aca2008-10-12 17:26:37 +02002789 if (curproxy == &defproxy) {
2790 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002793 }
2794
Willy Tarreau55ea7572007-06-17 19:56:27 +02002795 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002796 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002797
2798 if (*(args[1]) == 0) {
2799 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002802 }
2803
Willy Tarreauef6494c2010-01-28 17:12:36 +01002804 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002805 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2806 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002807 err_code |= ERR_ALERT | ERR_FATAL;
2808 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002809 }
2810
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002811 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2812 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2813 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002816 }
2817
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002818 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002819
Willy Tarreau55ea7572007-06-17 19:56:27 +02002820 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2821 rule->cond = cond;
2822 rule->be.name = strdup(args[1]);
2823 LIST_INIT(&rule->list);
2824 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2825 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002826 else if (strcmp(args[0], "use-server") == 0) {
2827 struct server_rule *rule;
2828
2829 if (curproxy == &defproxy) {
2830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834
2835 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2836 err_code |= ERR_WARN;
2837
2838 if (*(args[1]) == 0) {
2839 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
2843
2844 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2845 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2846 file, linenum, args[0]);
2847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
2849 }
2850
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002851 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2852 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2853 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002854 err_code |= ERR_ALERT | ERR_FATAL;
2855 goto out;
2856 }
2857
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002858 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002859
2860 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2861 rule->cond = cond;
2862 rule->srv.name = strdup(args[1]);
2863 LIST_INIT(&rule->list);
2864 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2865 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2866 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002867 else if ((!strcmp(args[0], "force-persist")) ||
2868 (!strcmp(args[0], "ignore-persist"))) {
2869 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002870
2871 if (curproxy == &defproxy) {
2872 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876
2877 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2878 err_code |= ERR_WARN;
2879
Willy Tarreauef6494c2010-01-28 17:12:36 +01002880 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002881 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2882 file, linenum, args[0]);
2883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
2885 }
2886
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002887 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2888 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2889 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892 }
2893
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002894 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2895 * where force-persist is applied.
2896 */
2897 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002898
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002899 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002900 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002901 if (!strcmp(args[0], "force-persist")) {
2902 rule->type = PERSIST_TYPE_FORCE;
2903 } else {
2904 rule->type = PERSIST_TYPE_IGNORE;
2905 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002906 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002907 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002908 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002909 else if (!strcmp(args[0], "stick-table")) {
2910 int myidx = 1;
2911
Emeric Brun32da3c42010-09-23 18:39:19 +02002912 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002913 curproxy->table.type = (unsigned int)-1;
2914 while (*args[myidx]) {
2915 const char *err;
2916
2917 if (strcmp(args[myidx], "size") == 0) {
2918 myidx++;
2919 if (!*(args[myidx])) {
2920 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2921 file, linenum, args[myidx-1]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2926 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2927 file, linenum, *err, args[myidx-1]);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002931 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002932 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002933 else if (strcmp(args[myidx], "peers") == 0) {
2934 myidx++;
2935 if (!*(args[myidx])) {
2936 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2937 file, linenum, args[myidx-1]);
2938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
2940 }
2941 curproxy->table.peers.name = strdup(args[myidx++]);
2942 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002943 else if (strcmp(args[myidx], "expire") == 0) {
2944 myidx++;
2945 if (!*(args[myidx])) {
2946 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2947 file, linenum, args[myidx-1]);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
2951 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2952 if (err) {
2953 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2954 file, linenum, *err, args[myidx-1]);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957 }
2958 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002959 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002960 }
2961 else if (strcmp(args[myidx], "nopurge") == 0) {
2962 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002963 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002964 }
2965 else if (strcmp(args[myidx], "type") == 0) {
2966 myidx++;
2967 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2968 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2969 file, linenum, args[myidx]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002973 /* myidx already points to next arg */
2974 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002975 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002976 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002977 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002978
2979 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002980 nw = args[myidx];
2981 while (*nw) {
2982 /* the "store" keyword supports a comma-separated list */
2983 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002984 sa = NULL; /* store arg */
2985 while (*nw && *nw != ',') {
2986 if (*nw == '(') {
2987 *nw = 0;
2988 sa = ++nw;
2989 while (*nw != ')') {
2990 if (!*nw) {
2991 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2992 file, linenum, args[0], cw);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996 nw++;
2997 }
2998 *nw = '\0';
2999 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003000 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003001 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003002 if (*nw)
3003 *nw++ = '\0';
3004 type = stktable_get_data_type(cw);
3005 if (type < 0) {
3006 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3007 file, linenum, args[0], cw);
3008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
3010 }
Willy Tarreauac782882010-06-20 10:41:54 +02003011
3012 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3013 switch (err) {
3014 case PE_NONE: break;
3015 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003016 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3017 file, linenum, args[0], cw);
3018 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003019 break;
3020
3021 case PE_ARG_MISSING:
3022 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3023 file, linenum, args[0], cw);
3024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026
3027 case PE_ARG_NOT_USED:
3028 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3029 file, linenum, args[0], cw);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032
3033 default:
3034 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3035 file, linenum, args[0], cw);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003038 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003039 }
3040 myidx++;
3041 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003042 else {
3043 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3044 file, linenum, args[myidx]);
3045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 }
3049
3050 if (!curproxy->table.size) {
3051 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3052 file, linenum);
3053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
3055 }
3056
3057 if (curproxy->table.type == (unsigned int)-1) {
3058 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3059 file, linenum);
3060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
3062 }
3063 }
3064 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003065 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003066 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003067 int myidx = 0;
3068 const char *name = NULL;
3069 int flags;
3070
3071 if (curproxy == &defproxy) {
3072 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
3075 }
3076
3077 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3078 err_code |= ERR_WARN;
3079 goto out;
3080 }
3081
3082 myidx++;
3083 if ((strcmp(args[myidx], "store") == 0) ||
3084 (strcmp(args[myidx], "store-request") == 0)) {
3085 myidx++;
3086 flags = STK_IS_STORE;
3087 }
3088 else if (strcmp(args[myidx], "store-response") == 0) {
3089 myidx++;
3090 flags = STK_IS_STORE | STK_ON_RSP;
3091 }
3092 else if (strcmp(args[myidx], "match") == 0) {
3093 myidx++;
3094 flags = STK_IS_MATCH;
3095 }
3096 else if (strcmp(args[myidx], "on") == 0) {
3097 myidx++;
3098 flags = STK_IS_MATCH | STK_IS_STORE;
3099 }
3100 else {
3101 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
3105
3106 if (*(args[myidx]) == 0) {
3107 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
3111
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003112 curproxy->conf.args.ctx = ARGC_STK;
3113 expr = sample_parse_expr(args, &myidx, trash.str, trash.size, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003114 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003115 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119
3120 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003121 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3122 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3123 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003124 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003125 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003126 goto out;
3127 }
3128 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003129 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3130 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3131 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003132 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003133 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003134 goto out;
3135 }
3136 }
3137
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003138 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003139 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003140
Emeric Brunb982a3d2010-01-04 15:45:53 +01003141 if (strcmp(args[myidx], "table") == 0) {
3142 myidx++;
3143 name = args[myidx++];
3144 }
3145
Willy Tarreauef6494c2010-01-28 17:12:36 +01003146 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003147 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3148 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3149 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003150 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003151 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003152 goto out;
3153 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003154 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003155 else if (*(args[myidx])) {
3156 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3157 file, linenum, args[0], args[myidx]);
3158 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003159 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003160 goto out;
3161 }
Emeric Brun97679e72010-09-23 17:56:44 +02003162 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003163 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003164 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003165 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003166
Emeric Brunb982a3d2010-01-04 15:45:53 +01003167 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3168 rule->cond = cond;
3169 rule->expr = expr;
3170 rule->flags = flags;
3171 rule->table.name = name ? strdup(name) : NULL;
3172 LIST_INIT(&rule->list);
3173 if (flags & STK_ON_RSP)
3174 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3175 else
3176 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003179 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003181
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3183 curproxy->uri_auth = NULL; /* we must detach from the default config */
3184
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003185 if (!*args[1]) {
3186 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003187 } else if (!strcmp(args[1], "admin")) {
3188 struct stats_admin_rule *rule;
3189
3190 if (curproxy == &defproxy) {
3191 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
3194 }
3195
3196 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3197 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3198 err_code |= ERR_ALERT | ERR_ABORT;
3199 goto out;
3200 }
3201
3202 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3203 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3204 file, linenum, args[0], args[1]);
3205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
3207 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003208 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3209 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3210 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003215 err_code |= warnif_cond_conflicts(cond,
3216 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3217 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003218
3219 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3220 rule->cond = cond;
3221 LIST_INIT(&rule->list);
3222 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 } else if (!strcmp(args[1], "uri")) {
3224 if (*(args[2]) == 0) {
3225 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3229 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_ABORT;
3231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 }
3233 } else if (!strcmp(args[1], "realm")) {
3234 if (*(args[2]) == 0) {
3235 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_ALERT | ERR_ABORT;
3241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003243 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003244 unsigned interval;
3245
3246 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3247 if (err) {
3248 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3249 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003252 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3253 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_ABORT;
3255 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003256 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003257 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003258 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003259
3260 if (curproxy == &defproxy) {
3261 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
3264 }
3265
3266 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3267 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3268 err_code |= ERR_ALERT | ERR_ABORT;
3269 goto out;
3270 }
3271
Willy Tarreauff011f22011-01-06 17:51:27 +01003272 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3273 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003274 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3275 file, linenum, args[0]);
3276 err_code |= ERR_WARN;
3277 }
3278
Willy Tarreauff011f22011-01-06 17:51:27 +01003279 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003280
Willy Tarreauff011f22011-01-06 17:51:27 +01003281 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003282 err_code |= ERR_ALERT | ERR_ABORT;
3283 goto out;
3284 }
3285
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003286 err_code |= warnif_cond_conflicts(rule->cond,
3287 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3288 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003289 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003290
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 } else if (!strcmp(args[1], "auth")) {
3292 if (*(args[2]) == 0) {
3293 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_ABORT;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
3301 } else if (!strcmp(args[1], "scope")) {
3302 if (*(args[2]) == 0) {
3303 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3307 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_ABORT;
3309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
3311 } else if (!strcmp(args[1], "enable")) {
3312 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_ALERT | ERR_ABORT;
3315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003317 } else if (!strcmp(args[1], "hide-version")) {
3318 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_ABORT;
3321 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003322 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003323 } else if (!strcmp(args[1], "show-legends")) {
3324 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3325 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3326 err_code |= ERR_ALERT | ERR_ABORT;
3327 goto out;
3328 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003329 } else if (!strcmp(args[1], "show-node")) {
3330
3331 if (*args[2]) {
3332 int i;
3333 char c;
3334
3335 for (i=0; args[2][i]; i++) {
3336 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003337 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3338 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003339 break;
3340 }
3341
3342 if (!i || args[2][i]) {
3343 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3344 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3345 file, linenum, args[0], args[1]);
3346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
3348 }
3349 }
3350
3351 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3352 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3353 err_code |= ERR_ALERT | ERR_ABORT;
3354 goto out;
3355 }
3356 } else if (!strcmp(args[1], "show-desc")) {
3357 char *desc = NULL;
3358
3359 if (*args[2]) {
3360 int i, len=0;
3361 char *d;
3362
3363 for(i=2; *args[i]; i++)
3364 len += strlen(args[i])+1;
3365
3366 desc = d = (char *)calloc(1, len);
3367
3368 d += sprintf(d, "%s", args[2]);
3369 for(i=3; *args[i]; i++)
3370 d += sprintf(d, " %s", args[i]);
3371 }
3372
3373 if (!*args[2] && !global.desc)
3374 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3375 file, linenum, args[1]);
3376 else {
3377 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3378 free(desc);
3379 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3380 err_code |= ERR_ALERT | ERR_ABORT;
3381 goto out;
3382 }
3383 free(desc);
3384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003386stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003387 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 +01003388 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 }
3392 }
3393 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003394 int optnum;
3395
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003396 if (*(args[1]) == '\0') {
3397 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3398 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003402
3403 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3404 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003405 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3406 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3407 file, linenum, cfg_opts[optnum].name);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
Willy Tarreau93893792009-07-23 13:19:11 +02003411 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3412 err_code |= ERR_WARN;
3413 goto out;
3414 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003415
Willy Tarreau3842f002009-06-14 11:39:52 +02003416 curproxy->no_options &= ~cfg_opts[optnum].val;
3417 curproxy->options &= ~cfg_opts[optnum].val;
3418
3419 switch (kwm) {
3420 case KWM_STD:
3421 curproxy->options |= cfg_opts[optnum].val;
3422 break;
3423 case KWM_NO:
3424 curproxy->no_options |= cfg_opts[optnum].val;
3425 break;
3426 case KWM_DEF: /* already cleared */
3427 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003428 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003429
Willy Tarreau93893792009-07-23 13:19:11 +02003430 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003431 }
3432 }
3433
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003434 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3435 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003436 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3437 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3438 file, linenum, cfg_opts2[optnum].name);
3439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
3441 }
Willy Tarreau93893792009-07-23 13:19:11 +02003442 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3443 err_code |= ERR_WARN;
3444 goto out;
3445 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003446
Willy Tarreau3842f002009-06-14 11:39:52 +02003447 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3448 curproxy->options2 &= ~cfg_opts2[optnum].val;
3449
3450 switch (kwm) {
3451 case KWM_STD:
3452 curproxy->options2 |= cfg_opts2[optnum].val;
3453 break;
3454 case KWM_NO:
3455 curproxy->no_options2 |= cfg_opts2[optnum].val;
3456 break;
3457 case KWM_DEF: /* already cleared */
3458 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003459 }
Willy Tarreau93893792009-07-23 13:19:11 +02003460 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003461 }
3462 }
3463
Willy Tarreau3842f002009-06-14 11:39:52 +02003464 if (kwm != KWM_STD) {
3465 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003466 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003469 }
3470
Emeric Brun3a058f32009-06-30 18:26:00 +02003471 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003472 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003474 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003475 if (*(args[2]) != '\0') {
3476 if (!strcmp(args[2], "clf")) {
3477 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003478 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003479 } else {
3480 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003483 }
3484 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003485 if (curproxy->conf.logformat_string != default_http_log_format &&
3486 curproxy->conf.logformat_string != default_tcp_log_format &&
3487 curproxy->conf.logformat_string != clf_http_log_format)
3488 free(curproxy->conf.logformat_string);
3489 curproxy->conf.logformat_string = logformat;
3490
3491 free(curproxy->conf.lfs_file);
3492 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3493 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003494 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003495 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003497 if (curproxy->conf.logformat_string != default_http_log_format &&
3498 curproxy->conf.logformat_string != default_tcp_log_format &&
3499 curproxy->conf.logformat_string != clf_http_log_format)
3500 free(curproxy->conf.logformat_string);
3501 curproxy->conf.logformat_string = default_tcp_log_format;
3502
3503 free(curproxy->conf.lfs_file);
3504 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3505 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 else if (!strcmp(args[1], "tcpka")) {
3508 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003509 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003511
3512 if (curproxy->cap & PR_CAP_FE)
3513 curproxy->options |= PR_O_TCP_CLI_KA;
3514 if (curproxy->cap & PR_CAP_BE)
3515 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 }
3517 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003518 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_WARN;
3520
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003522 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003523 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003524 curproxy->options2 &= ~PR_O2_CHK_ANY;
3525 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003526 if (!*args[2]) { /* no argument */
3527 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3528 curproxy->check_len = strlen(DEF_CHECK_REQ);
3529 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003530 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 curproxy->check_req = (char *)malloc(reqlen);
3532 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003533 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003535 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 if (*args[4])
3537 reqlen += strlen(args[4]);
3538 else
3539 reqlen += strlen("HTTP/1.0");
3540
3541 curproxy->check_req = (char *)malloc(reqlen);
3542 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003543 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003545 }
3546 else if (!strcmp(args[1], "ssl-hello-chk")) {
3547 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003548 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003550
Willy Tarreaua534fea2008-08-03 12:19:50 +02003551 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003552 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003553 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003554 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 }
Willy Tarreau23677902007-05-08 23:50:35 +02003556 else if (!strcmp(args[1], "smtpchk")) {
3557 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003558 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003559 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003560 curproxy->options2 &= ~PR_O2_CHK_ANY;
3561 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003562
3563 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3564 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3565 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3566 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3567 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3568 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3569 curproxy->check_req = (char *)malloc(reqlen);
3570 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3571 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3572 } else {
3573 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3574 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3575 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3576 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3577 }
3578 }
3579 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003580 else if (!strcmp(args[1], "pgsql-check")) {
3581 /* use PostgreSQL request to check servers' health */
3582 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3583 err_code |= ERR_WARN;
3584
3585 free(curproxy->check_req);
3586 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003587 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003588 curproxy->options2 |= PR_O2_PGSQL_CHK;
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 * packet;
3596 uint32_t packet_len;
3597 uint32_t pv;
3598
3599 /* suboption header - needs additional argument for it */
3600 if (*(args[cur_arg+1]) == 0) {
3601 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3602 file, linenum, args[0], args[1], args[cur_arg]);
3603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
3605 }
3606
3607 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3608 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3609 pv = htonl(0x30000); /* protocol version 3.0 */
3610
3611 packet = (char*) calloc(1, packet_len);
3612
3613 memcpy(packet + 4, &pv, 4);
3614
3615 /* copy "user" */
3616 memcpy(packet + 8, "user", 4);
3617
3618 /* copy username */
3619 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3620
3621 free(curproxy->check_req);
3622 curproxy->check_req = packet;
3623 curproxy->check_len = packet_len;
3624
3625 packet_len = htonl(packet_len);
3626 memcpy(packet, &packet_len, 4);
3627 cur_arg += 2;
3628 } else {
3629 /* unknown suboption - catchall */
3630 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3631 file, linenum, args[0], args[1]);
3632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
3634 }
3635 } /* end while loop */
3636 }
3637 }
3638
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003639 else if (!strcmp(args[1], "redis-check")) {
3640 /* use REDIS PING request to check servers' health */
3641 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3642 err_code |= ERR_WARN;
3643
3644 free(curproxy->check_req);
3645 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003646 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003647 curproxy->options2 |= PR_O2_REDIS_CHK;
3648
3649 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3650 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3651 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3652 }
3653
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003654 else if (!strcmp(args[1], "mysql-check")) {
3655 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003656 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3657 err_code |= ERR_WARN;
3658
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003659 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003660 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003661 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003662 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003663
3664 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3665 * const char mysql40_client_auth_pkt[] = {
3666 * "\x0e\x00\x00" // packet length
3667 * "\x01" // packet number
3668 * "\x00\x00" // client capabilities
3669 * "\x00\x00\x01" // max packet
3670 * "haproxy\x00" // username (null terminated string)
3671 * "\x00" // filler (always 0x00)
3672 * "\x01\x00\x00" // packet length
3673 * "\x00" // packet number
3674 * "\x01" // COM_QUIT command
3675 * };
3676 */
3677
3678 if (*(args[2])) {
3679 int cur_arg = 2;
3680
3681 while (*(args[cur_arg])) {
3682 if (strcmp(args[cur_arg], "user") == 0) {
3683 char *mysqluser;
3684 int packetlen, reqlen, userlen;
3685
3686 /* suboption header - needs additional argument for it */
3687 if (*(args[cur_arg+1]) == 0) {
3688 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3689 file, linenum, args[0], args[1], args[cur_arg]);
3690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
3692 }
3693 mysqluser = args[cur_arg + 1];
3694 userlen = strlen(mysqluser);
3695 packetlen = userlen + 7;
3696 reqlen = packetlen + 9;
3697
3698 free(curproxy->check_req);
3699 curproxy->check_req = (char *)calloc(1, reqlen);
3700 curproxy->check_len = reqlen;
3701
3702 snprintf(curproxy->check_req, 4, "%c%c%c",
3703 ((unsigned char) packetlen & 0xff),
3704 ((unsigned char) (packetlen >> 8) & 0xff),
3705 ((unsigned char) (packetlen >> 16) & 0xff));
3706
3707 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003708 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003709 curproxy->check_req[8] = 1;
3710 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3711 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3712 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3713 cur_arg += 2;
3714 } else {
3715 /* unknown suboption - catchall */
3716 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3717 file, linenum, args[0], args[1]);
3718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
3720 }
3721 } /* end while loop */
3722 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003723 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003724 else if (!strcmp(args[1], "ldap-check")) {
3725 /* use LDAP request to check servers' health */
3726 free(curproxy->check_req);
3727 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003728 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003729 curproxy->options2 |= PR_O2_LDAP_CHK;
3730
3731 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3732 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3733 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3734 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003735 else if (!strcmp(args[1], "tcp-check")) {
3736 /* use raw TCPCHK send/expect to check servers' health */
3737 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3738 err_code |= ERR_WARN;
3739
3740 free(curproxy->check_req);
3741 curproxy->check_req = NULL;
3742 curproxy->options2 &= ~PR_O2_CHK_ANY;
3743 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3744 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003745 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003746 int cur_arg;
3747
3748 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3749 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003750 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003751
Willy Tarreau87cf5142011-08-19 22:57:24 +02003752 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003753
3754 free(curproxy->fwdfor_hdr_name);
3755 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3756 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3757
3758 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3759 cur_arg = 2;
3760 while (*(args[cur_arg])) {
3761 if (!strcmp(args[cur_arg], "except")) {
3762 /* suboption except - needs additional argument for it */
3763 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3764 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3765 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003768 }
3769 /* flush useless bits */
3770 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003771 cur_arg += 2;
3772 } else if (!strcmp(args[cur_arg], "header")) {
3773 /* suboption header - needs additional argument for it */
3774 if (*(args[cur_arg+1]) == 0) {
3775 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3776 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003779 }
3780 free(curproxy->fwdfor_hdr_name);
3781 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3782 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3783 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003784 } else if (!strcmp(args[cur_arg], "if-none")) {
3785 curproxy->options &= ~PR_O_FF_ALWAYS;
3786 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003787 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003788 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003789 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003790 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003793 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003794 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003795 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003796 else if (!strcmp(args[1], "originalto")) {
3797 int cur_arg;
3798
3799 /* insert x-original-to field, but not for the IP address listed as an except.
3800 * set default options (ie: bitfield, header name, etc)
3801 */
3802
3803 curproxy->options |= PR_O_ORGTO;
3804
3805 free(curproxy->orgto_hdr_name);
3806 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3807 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3808
Willy Tarreau87cf5142011-08-19 22:57:24 +02003809 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003810 cur_arg = 2;
3811 while (*(args[cur_arg])) {
3812 if (!strcmp(args[cur_arg], "except")) {
3813 /* suboption except - needs additional argument for it */
3814 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3815 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3816 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003819 }
3820 /* flush useless bits */
3821 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3822 cur_arg += 2;
3823 } else if (!strcmp(args[cur_arg], "header")) {
3824 /* suboption header - needs additional argument for it */
3825 if (*(args[cur_arg+1]) == 0) {
3826 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3827 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003830 }
3831 free(curproxy->orgto_hdr_name);
3832 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3833 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3834 cur_arg += 2;
3835 } else {
3836 /* unknown suboption - catchall */
3837 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3838 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003841 }
3842 } /* end while loop */
3843 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 else {
3845 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 }
Willy Tarreau93893792009-07-23 13:19:11 +02003849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003851 else if (!strcmp(args[0], "default_backend")) {
3852 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003854
3855 if (*(args[1]) == 0) {
3856 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003859 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003860 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003861 curproxy->defbe.name = strdup(args[1]);
3862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003866
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003867 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3868 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003869 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003870 /* enable reconnections to dispatch */
3871 curproxy->options |= PR_O_REDISP;
3872 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003873 else if (!strcmp(args[0], "http-check")) {
3874 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003876
3877 if (strcmp(args[1], "disable-on-404") == 0) {
3878 /* enable a graceful server shutdown on an HTTP 404 response */
3879 curproxy->options |= PR_O_DISABLE404;
3880 }
Willy Tarreauef781042010-01-27 11:53:01 +01003881 else if (strcmp(args[1], "send-state") == 0) {
3882 /* enable emission of the apparent state of a server in HTTP checks */
3883 curproxy->options2 |= PR_O2_CHK_SNDST;
3884 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003885 else if (strcmp(args[1], "expect") == 0) {
3886 const char *ptr_arg;
3887 int cur_arg;
3888
3889 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3890 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
3893 }
3894
3895 cur_arg = 2;
3896 /* consider exclamation marks, sole or at the beginning of a word */
3897 while (*(ptr_arg = args[cur_arg])) {
3898 while (*ptr_arg == '!') {
3899 curproxy->options2 ^= PR_O2_EXP_INV;
3900 ptr_arg++;
3901 }
3902 if (*ptr_arg)
3903 break;
3904 cur_arg++;
3905 }
3906 /* now ptr_arg points to the beginning of a word past any possible
3907 * exclamation mark, and cur_arg is the argument which holds this word.
3908 */
3909 if (strcmp(ptr_arg, "status") == 0) {
3910 if (!*(args[cur_arg + 1])) {
3911 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3912 file, linenum, args[0], args[1], ptr_arg);
3913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
3915 }
3916 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003917 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003918 curproxy->expect_str = strdup(args[cur_arg + 1]);
3919 }
3920 else if (strcmp(ptr_arg, "string") == 0) {
3921 if (!*(args[cur_arg + 1])) {
3922 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3923 file, linenum, args[0], args[1], ptr_arg);
3924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
3926 }
3927 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003928 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003929 curproxy->expect_str = strdup(args[cur_arg + 1]);
3930 }
3931 else if (strcmp(ptr_arg, "rstatus") == 0) {
3932 if (!*(args[cur_arg + 1])) {
3933 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3934 file, linenum, args[0], args[1], ptr_arg);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003939 free(curproxy->expect_str);
3940 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3941 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003942 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3943 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3944 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3945 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
3949 }
3950 else if (strcmp(ptr_arg, "rstring") == 0) {
3951 if (!*(args[cur_arg + 1])) {
3952 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3953 file, linenum, args[0], args[1], ptr_arg);
3954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
3956 }
3957 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003958 free(curproxy->expect_str);
3959 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3960 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003961 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3962 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3963 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3964 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
3967 }
3968 }
3969 else {
3970 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3971 file, linenum, args[0], args[1], ptr_arg);
3972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
3974 }
3975 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003976 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003977 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 +02003978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003980 }
3981 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003982 else if (!strcmp(args[0], "tcp-check")) {
3983 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3984 err_code |= ERR_WARN;
3985
3986 if (strcmp(args[1], "send") == 0) {
3987 if (! *(args[2]) ) {
3988 /* SEND string expected */
3989 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
3990 file, linenum, args[0], args[1], args[2]);
3991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
3993 } else {
3994 struct tcpcheck_rule *tcpcheck;
3995
3996 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
3997
3998 tcpcheck->action = TCPCHK_ACT_SEND;
3999 tcpcheck->string_len = strlen(args[2]);
4000 tcpcheck->string = strdup(args[2]);
4001 tcpcheck->expect_regex = NULL;
4002
4003 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4004 }
4005 }
4006 else if (strcmp(args[1], "send-binary") == 0) {
4007 if (! *(args[2]) ) {
4008 /* SEND binary string expected */
4009 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4010 file, linenum, args[0], args[1], args[2]);
4011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
4013 } else {
4014 struct tcpcheck_rule *tcpcheck;
4015 char *err = NULL;
4016
4017 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4018
4019 tcpcheck->action = TCPCHK_ACT_SEND;
4020 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4021 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4022 file, linenum, args[0], args[1], args[2], err);
4023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
4025 }
4026 tcpcheck->expect_regex = NULL;
4027
4028 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4029 }
4030 }
4031 else if (strcmp(args[1], "expect") == 0) {
4032 const char *ptr_arg;
4033 int cur_arg;
4034 int inverse = 0;
4035
4036 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4037 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
4040 }
4041
4042 cur_arg = 2;
4043 /* consider exclamation marks, sole or at the beginning of a word */
4044 while (*(ptr_arg = args[cur_arg])) {
4045 while (*ptr_arg == '!') {
4046 inverse = !inverse;
4047 ptr_arg++;
4048 }
4049 if (*ptr_arg)
4050 break;
4051 cur_arg++;
4052 }
4053 /* now ptr_arg points to the beginning of a word past any possible
4054 * exclamation mark, and cur_arg is the argument which holds this word.
4055 */
4056 if (strcmp(ptr_arg, "binary") == 0) {
4057 if (!*(args[cur_arg + 1])) {
4058 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4059 file, linenum, args[0], args[1], ptr_arg);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063 struct tcpcheck_rule *tcpcheck;
4064 char *err = NULL;
4065
4066 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4067
4068 tcpcheck->action = TCPCHK_ACT_EXPECT;
4069 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4070 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4071 file, linenum, args[0], args[1], args[2], err);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075 tcpcheck->expect_regex = NULL;
4076 tcpcheck->inverse = inverse;
4077
4078 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4079 }
4080 else if (strcmp(ptr_arg, "string") == 0) {
4081 if (!*(args[cur_arg + 1])) {
4082 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4083 file, linenum, args[0], args[1], ptr_arg);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087 struct tcpcheck_rule *tcpcheck;
4088
4089 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4090
4091 tcpcheck->action = TCPCHK_ACT_EXPECT;
4092 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4093 tcpcheck->string = strdup(args[cur_arg + 1]);
4094 tcpcheck->expect_regex = NULL;
4095 tcpcheck->inverse = inverse;
4096
4097 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4098 }
4099 else if (strcmp(ptr_arg, "rstring") == 0) {
4100 if (!*(args[cur_arg + 1])) {
4101 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4102 file, linenum, args[0], args[1], ptr_arg);
4103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
4105 }
4106 struct tcpcheck_rule *tcpcheck;
4107
4108 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4109
4110 tcpcheck->action = TCPCHK_ACT_EXPECT;
4111 tcpcheck->string_len = 0;
4112 tcpcheck->string = NULL;
4113 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4114 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4115 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4116 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119 }
4120 tcpcheck->inverse = inverse;
4121
4122 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4123 }
4124 else {
4125 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4126 file, linenum, args[0], args[1], ptr_arg);
4127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
4129 }
4130 }
4131 else {
4132 Alert("parsing [%s:%d] : '%s' only supports 'send' or 'expect'.\n", file, linenum, args[0]);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004137 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004138 if (curproxy == &defproxy) {
4139 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004142 }
4143
Willy Tarreaub80c2302007-11-30 20:51:32 +01004144 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004146
4147 if (strcmp(args[1], "fail") == 0) {
4148 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004149 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004150 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4151 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004154 }
4155
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004156 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4157 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4158 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004161 }
4162 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4163 }
4164 else {
4165 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004168 }
4169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170#ifdef TPROXY
4171 else if (!strcmp(args[0], "transparent")) {
4172 /* enable transparent proxy connections */
4173 curproxy->options |= PR_O_TRANSP;
4174 }
4175#endif
4176 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004177 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004178 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004179
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 if (*(args[1]) == 0) {
4181 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004184 }
4185 curproxy->maxconn = atol(args[1]);
4186 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004187 else if (!strcmp(args[0], "backlog")) { /* backlog */
4188 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004189 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004190
4191 if (*(args[1]) == 0) {
4192 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004195 }
4196 curproxy->backlog = atol(args[1]);
4197 }
Willy Tarreau86034312006-12-29 00:10:33 +01004198 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004199 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004201
Willy Tarreau86034312006-12-29 00:10:33 +01004202 if (*(args[1]) == 0) {
4203 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004204 err_code |= ERR_ALERT | ERR_FATAL;
4205 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004206 }
4207 curproxy->fullconn = atol(args[1]);
4208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4210 if (*(args[1]) == 0) {
4211 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004214 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004215 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4216 if (err) {
4217 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4218 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004221 }
4222 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 }
4224 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004225 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004226 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004227 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004228
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229 if (curproxy == &defproxy) {
4230 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004234 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004235 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004236
Willy Tarreau902636f2013-03-10 19:44:48 +01004237 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004238 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004239 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004240 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004241 goto out;
4242 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004243
4244 proto = protocol_by_family(sk->ss_family);
4245 if (!proto || !proto->connect) {
4246 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4247 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 }
4251
4252 if (port1 != port2) {
4253 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4254 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004258
4259 if (!port1) {
4260 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4261 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004265
Willy Tarreaud5191e72010-02-09 20:50:45 +01004266 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004267 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004268 }
4269 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004270 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004271 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004272
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004273 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4274 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004279 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004280 /**
4281 * The syntax for hash-type config element is
4282 * hash-type {map-based|consistent} [[<algo>] avalanche]
4283 *
4284 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4285 */
4286 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004287
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004288 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4289 err_code |= ERR_WARN;
4290
4291 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004292 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4293 }
4294 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004295 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4296 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004297 else if (strcmp(args[1], "avalanche") == 0) {
4298 Alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
4299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004301 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004302 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004303 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
4306 }
Bhaskar98634f02013-10-29 23:30:51 -04004307
4308 /* set the hash function to use */
4309 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004310 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004311 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004312
4313 /* if consistent with no argument, then avalanche modifier is also applied */
4314 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4315 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004316 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004317 /* set the hash function */
4318 if (!strcmp(args[2], "sdbm")) {
4319 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4320 }
4321 else if (!strcmp(args[2], "djb2")) {
4322 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004323 } else if (!strcmp(args[2], "wt6")) {
4324 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004325 }
4326 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004327 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
4330 }
4331
4332 /* set the hash modifier */
4333 if (!strcmp(args[3], "avalanche")) {
4334 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4335 }
4336 else if (*args[3]) {
4337 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4338 err_code |= ERR_ALERT | ERR_FATAL;
4339 goto out;
4340 }
Bhaskar98634f02013-10-29 23:30:51 -04004341 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004342 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004343 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004344 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004345 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004346 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004347
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004348 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004352 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004353 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004354 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004355
4356 if (!*args[2]) {
4357 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4358 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004362
4363 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004364 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004365 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4366 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004369 }
4370
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004371 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004372 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004373 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004374 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004375
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004376 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4377 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4378 err_code |= ERR_ALERT | ERR_ABORT;
4379 goto out;
4380 }
4381
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004382 /* the servers are linked backwards first */
4383 newsrv->next = curproxy->srv;
4384 curproxy->srv = newsrv;
4385 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004386 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004387 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004388
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004389 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004390 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004391 LIST_INIT(&newsrv->pendconns);
4392 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004393 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004394 newsrv->state = SRV_RUNNING; /* early server setup */
4395 newsrv->last_change = now.tv_sec;
4396 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004398 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004399 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004400 * - IP: => port=+0, relative
4401 * - IP:N => port=N, absolute
4402 * - IP:+N => port=+N, relative
4403 * - IP:-N => port=-N, relative
4404 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004405 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004406 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004407 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004408 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004409 goto out;
4410 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004411
4412 proto = protocol_by_family(sk->ss_family);
4413 if (!proto || !proto->connect) {
4414 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4415 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
4418 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004419
4420 if (!port1 || !port2) {
4421 /* no port specified, +offset, -offset */
4422 newsrv->state |= SRV_MAPPORTS;
4423 }
4424 else if (port1 != port2) {
4425 /* port range */
4426 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4427 file, linenum, args[0], args[1], args[2]);
4428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
4430 }
4431 else {
4432 /* used by checks */
4433 realport = port1;
4434 }
4435
Willy Tarreaud5191e72010-02-09 20:50:45 +01004436 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004437 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4438 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004439
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004440 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004441 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4442 file, linenum, newsrv->addr.ss_family, args[2]);
4443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
4445 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004446
Simon Hormand60d6912013-11-25 10:46:36 +09004447 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004448 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004449 newsrv->check.inter = curproxy->defsrv.check.inter;
4450 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4451 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004452 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4453 newsrv->agent.port = curproxy->defsrv.agent.port;
4454 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4455 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4456 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004457 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4458 newsrv->minconn = curproxy->defsrv.minconn;
4459 newsrv->maxconn = curproxy->defsrv.maxconn;
4460 newsrv->slowstart = curproxy->defsrv.slowstart;
4461 newsrv->onerror = curproxy->defsrv.onerror;
4462 newsrv->consecutive_errors_limit
4463 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004464#ifdef OPENSSL
4465 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4466#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004467 newsrv->uweight = newsrv->iweight
4468 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004469
Simon Horman69d29f92013-02-23 15:14:19 +09004470 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004471 newsrv->check.rise = curproxy->defsrv.check.rise;
4472 newsrv->check.fall = curproxy->defsrv.check.fall;
4473 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004474 newsrv->check.server = newsrv;
4475
Simon Hormand60d6912013-11-25 10:46:36 +09004476 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004477 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4478 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4479 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004480 newsrv->agent.server = newsrv;
4481
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004482 cur_arg = 3;
4483 } else {
4484 newsrv = &curproxy->defsrv;
4485 cur_arg = 1;
4486 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004487
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004489 if (!strcmp(args[cur_arg], "agent-check")) {
4490 global.maxsock++;
4491 do_agent = 1;
4492 cur_arg += 1;
4493 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4494 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4495 if (err) {
4496 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4497 file, linenum, *err, newsrv->id);
4498 err_code |= ERR_ALERT | ERR_FATAL;
4499 goto out;
4500 }
4501 if (val <= 0) {
4502 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4503 file, linenum, val, args[cur_arg], newsrv->id);
4504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
4506 }
4507 newsrv->agent.inter = val;
4508 cur_arg += 2;
4509 }
4510 else if (!strcmp(args[cur_arg], "agent-port")) {
4511 global.maxsock++;
4512 newsrv->agent.port = atol(args[cur_arg + 1]);
4513 cur_arg += 2;
4514 }
4515 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 newsrv->cookie = strdup(args[cur_arg + 1]);
4517 newsrv->cklen = strlen(args[cur_arg + 1]);
4518 cur_arg += 2;
4519 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004520 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004521 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4522 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4523 cur_arg += 2;
4524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004525 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004526 if (!*args[cur_arg + 1]) {
4527 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4528 file, linenum, args[cur_arg]);
4529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
4531 }
4532
Simon Horman58c32972013-11-25 10:46:38 +09004533 newsrv->check.rise = atol(args[cur_arg + 1]);
4534 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004535 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4536 file, linenum, args[cur_arg]);
4537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
4539 }
4540
Simon Horman125d0992013-02-24 17:23:38 +09004541 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004542 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004543 cur_arg += 2;
4544 }
4545 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004546 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004547
4548 if (!*args[cur_arg + 1]) {
4549 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4550 file, linenum, args[cur_arg]);
4551 err_code |= ERR_ALERT | ERR_FATAL;
4552 goto out;
4553 }
4554
Simon Horman58c32972013-11-25 10:46:38 +09004555 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004556 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4557 file, linenum, args[cur_arg]);
4558 err_code |= ERR_ALERT | ERR_FATAL;
4559 goto out;
4560 }
4561
Willy Tarreaubaaee002006-06-26 02:48:02 +02004562 cur_arg += 2;
4563 }
4564 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004565 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4566 if (err) {
4567 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4568 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004569 err_code |= ERR_ALERT | ERR_FATAL;
4570 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004571 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004572 if (val <= 0) {
4573 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4574 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004575 err_code |= ERR_ALERT | ERR_FATAL;
4576 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004577 }
Simon Horman66183002013-02-23 10:16:43 +09004578 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 cur_arg += 2;
4580 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004581 else if (!strcmp(args[cur_arg], "fastinter")) {
4582 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4583 if (err) {
4584 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4585 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004588 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004589 if (val <= 0) {
4590 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4591 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004594 }
Simon Horman66183002013-02-23 10:16:43 +09004595 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004596 cur_arg += 2;
4597 }
4598 else if (!strcmp(args[cur_arg], "downinter")) {
4599 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4600 if (err) {
4601 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4602 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004605 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004606 if (val <= 0) {
4607 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4608 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004609 err_code |= ERR_ALERT | ERR_FATAL;
4610 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004611 }
Simon Horman66183002013-02-23 10:16:43 +09004612 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004613 cur_arg += 2;
4614 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004615 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004616 struct sockaddr_storage *sk;
4617 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004618 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004619
Willy Tarreau902636f2013-03-10 19:44:48 +01004620 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004621 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004622 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004623 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004624 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004625 goto out;
4626 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004627
4628 proto = protocol_by_family(sk->ss_family);
4629 if (!proto || !proto->connect) {
4630 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004631 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004635
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004636 if (port1 != port2) {
4637 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4638 file, linenum, args[cur_arg], args[cur_arg + 1]);
4639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
4641 }
4642
Simon Horman66183002013-02-23 10:16:43 +09004643 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004644 cur_arg += 2;
4645 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004646 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004647 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 cur_arg += 2;
4649 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004650 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 newsrv->state |= SRV_BACKUP;
4652 cur_arg ++;
4653 }
Simon Hormanfa461682011-06-25 09:39:49 +09004654 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4655 newsrv->state |= SRV_NON_STICK;
4656 cur_arg ++;
4657 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004658 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4659 newsrv->state |= SRV_SEND_PROXY;
4660 cur_arg ++;
4661 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004662 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4663 newsrv->check.send_proxy = 1;
4664 cur_arg ++;
4665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004666 else if (!strcmp(args[cur_arg], "weight")) {
4667 int w;
4668 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004669 if (w < 0 || w > SRV_UWGHT_MAX) {
4670 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4671 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004674 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004675 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 cur_arg += 2;
4677 }
4678 else if (!strcmp(args[cur_arg], "minconn")) {
4679 newsrv->minconn = atol(args[cur_arg + 1]);
4680 cur_arg += 2;
4681 }
4682 else if (!strcmp(args[cur_arg], "maxconn")) {
4683 newsrv->maxconn = atol(args[cur_arg + 1]);
4684 cur_arg += 2;
4685 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004686 else if (!strcmp(args[cur_arg], "maxqueue")) {
4687 newsrv->maxqueue = atol(args[cur_arg + 1]);
4688 cur_arg += 2;
4689 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004690 else if (!strcmp(args[cur_arg], "slowstart")) {
4691 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004692 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004693 if (err) {
4694 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4695 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004696 err_code |= ERR_ALERT | ERR_FATAL;
4697 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004698 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004699 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004700 cur_arg += 2;
4701 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004702 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004703
4704 if (!*args[cur_arg + 1]) {
4705 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4706 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004709 }
4710
4711 newsrv->trackit = strdup(args[cur_arg + 1]);
4712
4713 cur_arg += 2;
4714 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004715 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004716 global.maxsock++;
4717 do_check = 1;
4718 cur_arg += 1;
4719 }
Willy Tarreau96839092010-03-29 10:02:24 +02004720 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4721 newsrv->state |= SRV_MAINTAIN;
4722 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09004723 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004724 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004725 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004726 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004727 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004728 if (!strcmp(args[cur_arg + 1], "none"))
4729 newsrv->observe = HANA_OBS_NONE;
4730 else if (!strcmp(args[cur_arg + 1], "layer4"))
4731 newsrv->observe = HANA_OBS_LAYER4;
4732 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4733 if (curproxy->mode != PR_MODE_HTTP) {
4734 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4735 file, linenum, args[cur_arg + 1]);
4736 err_code |= ERR_ALERT;
4737 }
4738 newsrv->observe = HANA_OBS_LAYER7;
4739 }
4740 else {
4741 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004742 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004743 file, linenum, args[cur_arg], args[cur_arg + 1]);
4744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
4746 }
4747
4748 cur_arg += 2;
4749 }
4750 else if (!strcmp(args[cur_arg], "on-error")) {
4751 if (!strcmp(args[cur_arg + 1], "fastinter"))
4752 newsrv->onerror = HANA_ONERR_FASTINTER;
4753 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4754 newsrv->onerror = HANA_ONERR_FAILCHK;
4755 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4756 newsrv->onerror = HANA_ONERR_SUDDTH;
4757 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4758 newsrv->onerror = HANA_ONERR_MARKDWN;
4759 else {
4760 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004761 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004762 file, linenum, args[cur_arg], args[cur_arg + 1]);
4763 err_code |= ERR_ALERT | ERR_FATAL;
4764 goto out;
4765 }
4766
4767 cur_arg += 2;
4768 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004769 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4770 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4771 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4772 else {
4773 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4774 file, linenum, args[cur_arg], args[cur_arg + 1]);
4775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
4777 }
4778
4779 cur_arg += 2;
4780 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004781 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4782 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4783 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4784 else {
4785 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4786 file, linenum, args[cur_arg], args[cur_arg + 1]);
4787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
4789 }
4790
4791 cur_arg += 2;
4792 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004793 else if (!strcmp(args[cur_arg], "error-limit")) {
4794 if (!*args[cur_arg + 1]) {
4795 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4796 file, linenum, args[cur_arg]);
4797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
4799 }
4800
4801 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4802
4803 if (newsrv->consecutive_errors_limit <= 0) {
4804 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4805 file, linenum, args[cur_arg]);
4806 err_code |= ERR_ALERT | ERR_FATAL;
4807 goto out;
4808 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004809 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004810 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004811 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004812 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004813 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004814 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004815
Willy Tarreaubaaee002006-06-26 02:48:02 +02004816 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004817 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4818 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004821 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004822
Willy Tarreauef9a3602012-12-08 22:29:20 +01004823 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004824 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004825 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004826 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004827 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004828 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004829 goto out;
4830 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004831
4832 proto = protocol_by_family(sk->ss_family);
4833 if (!proto || !proto->connect) {
4834 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4835 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
4838 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004839
Willy Tarreauef9a3602012-12-08 22:29:20 +01004840 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004841
4842 if (port_low != port_high) {
4843 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004844
4845 if (!port_low || !port_high) {
4846 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4847 file, linenum, args[cur_arg], args[cur_arg + 1]);
4848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
4850 }
4851
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004852 if (port_low <= 0 || port_low > 65535 ||
4853 port_high <= 0 || port_high > 65535 ||
4854 port_low > port_high) {
4855 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4856 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004857 err_code |= ERR_ALERT | ERR_FATAL;
4858 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004859 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004860 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4861 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4862 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004863 }
4864
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004866 while (*(args[cur_arg])) {
4867 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004868#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4869#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004870 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004871 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4872 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004875 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004876#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004877 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004878 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004879 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004882 }
4883 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004884 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4885 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004886 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004887 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4888 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004889 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4890 char *name, *end;
4891
4892 name = args[cur_arg+1] + 7;
4893 while (isspace(*name))
4894 name++;
4895
4896 end = name;
4897 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4898 end++;
4899
Willy Tarreauef9a3602012-12-08 22:29:20 +01004900 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4901 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4902 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4903 newsrv->conn_src.bind_hdr_len = end - name;
4904 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4905 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4906 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004907
4908 /* now look for an occurrence number */
4909 while (isspace(*end))
4910 end++;
4911 if (*end == ',') {
4912 end++;
4913 name = end;
4914 if (*end == '-')
4915 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004916 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004917 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004918 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004919 }
4920
Willy Tarreauef9a3602012-12-08 22:29:20 +01004921 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004922 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4923 " occurrences values smaller than %d.\n",
4924 file, linenum, MAX_HDR_HISTORY);
4925 err_code |= ERR_ALERT | ERR_FATAL;
4926 goto out;
4927 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004928 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004929 struct sockaddr_storage *sk;
4930 int port1, port2;
4931
Willy Tarreau902636f2013-03-10 19:44:48 +01004932 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004933 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004934 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004935 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004936 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004937 goto out;
4938 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004939
4940 proto = protocol_by_family(sk->ss_family);
4941 if (!proto || !proto->connect) {
4942 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4943 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
4946 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004947
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004948 if (port1 != port2) {
4949 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4950 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004951 err_code |= ERR_ALERT | ERR_FATAL;
4952 goto out;
4953 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004954 newsrv->conn_src.tproxy_addr = *sk;
4955 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004956 }
4957 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004958#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004959 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004960#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004961 cur_arg += 2;
4962 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004963#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004964 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004965 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004968#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004969 } /* "usesrc" */
4970
4971 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4972#ifdef SO_BINDTODEVICE
4973 if (!*args[cur_arg + 1]) {
4974 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4975 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004976 err_code |= ERR_ALERT | ERR_FATAL;
4977 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004978 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004979 free(newsrv->conn_src.iface_name);
4980 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4981 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004982 global.last_checks |= LSTCHK_NETADM;
4983#else
4984 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4985 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004988#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004989 cur_arg += 2;
4990 continue;
4991 }
4992 /* this keyword in not an option of "source" */
4993 break;
4994 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004996 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004997 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4998 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005003 static int srv_dumped;
5004 struct srv_kw *kw;
5005 char *err;
5006
5007 kw = srv_find_kw(args[cur_arg]);
5008 if (kw) {
5009 char *err = NULL;
5010 int code;
5011
5012 if (!kw->parse) {
5013 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5014 file, linenum, args[0], args[1], args[cur_arg]);
5015 cur_arg += 1 + kw->skip ;
5016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
5018 }
5019
5020 if (defsrv && !kw->default_ok) {
5021 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5022 file, linenum, args[0], args[1], args[cur_arg]);
5023 cur_arg += 1 + kw->skip ;
5024 err_code |= ERR_ALERT;
5025 continue;
5026 }
5027
5028 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5029 err_code |= code;
5030
5031 if (code) {
5032 if (err && *err) {
5033 indent_msg(&err, 2);
5034 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5035 }
5036 else
5037 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5038 file, linenum, args[0], args[1], args[cur_arg]);
5039 if (code & ERR_FATAL) {
5040 free(err);
5041 cur_arg += 1 + kw->skip;
5042 goto out;
5043 }
5044 }
5045 free(err);
5046 cur_arg += 1 + kw->skip;
5047 continue;
5048 }
5049
5050 err = NULL;
5051 if (!srv_dumped) {
5052 srv_dump_kws(&err);
5053 indent_msg(&err, 4);
5054 srv_dumped = 1;
5055 }
5056
5057 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5058 file, linenum, args[0], args[1], args[cur_arg],
5059 err ? " Registered keywords :" : "", err ? err : "");
5060 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005061
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 }
5065 }
5066
Simon Horman8c3d0be2013-11-25 10:46:40 +09005067 /* Set initial drain state using now-configured weight */
5068 set_server_drain_state(newsrv);
5069
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005071 int ret;
5072
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005073 if (newsrv->trackit) {
5074 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5075 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_ALERT | ERR_FATAL;
5077 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005078 }
5079
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005080 /* If neither a port nor an addr was specified and no check transport
5081 * layer is forced, then the transport layer used by the checks is the
5082 * same as for the production traffic. Otherwise we use raw_sock by
5083 * default, unless one is specified.
5084 */
Simon Horman66183002013-02-23 10:16:43 +09005085 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005086#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005087 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02005088#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005089 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5090 }
Simon Horman66183002013-02-23 10:16:43 +09005091 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005092 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005093 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005094
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005095 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005096 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005097
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005098 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005099 /* not yet valid, because no port was set on
5100 * the server either. We'll check if we have
5101 * a known port on the first listener.
5102 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005103 struct listener *l;
5104
5105 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005106 newsrv->check.port = get_host_port(&l->addr);
5107 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005108 break;
5109 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005110 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005111 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5113 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005117
Willy Tarreau2f075e92013-12-03 11:11:34 +01005118 /* note: check type will be set during the config review phase */
5119 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005120 if (ret) {
5121 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005122 goto out;
5123 }
5124
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 newsrv->state |= SRV_CHECKED;
5126 }
5127
Simon Hormand60d6912013-11-25 10:46:36 +09005128 if (do_agent) {
5129 int ret;
5130
5131 if (!newsrv->agent.port) {
5132 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5133 file, linenum, newsrv->id);
5134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
5136 }
5137
5138 if (!newsrv->agent.inter)
5139 newsrv->agent.inter = newsrv->check.inter;
5140
5141 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5142 if (ret) {
5143 err_code |= ret;
5144 goto out;
5145 }
5146
5147 newsrv->state |= SRV_AGENT_CHECKED;
5148 }
5149
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005150 if (!defsrv) {
5151 if (newsrv->state & SRV_BACKUP)
5152 curproxy->srv_bck++;
5153 else
5154 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005155
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005156 newsrv->prev_state = newsrv->state;
5157 }
William Lallemanda73203e2012-03-12 12:48:57 +01005158 }
5159
5160 else if (strcmp(args[0], "unique-id-format") == 0) {
5161 if (!*(args[1])) {
5162 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
5165 }
William Lallemand3203ff42012-11-11 17:30:56 +01005166 if (*(args[2])) {
5167 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5168 err_code |= ERR_ALERT | ERR_FATAL;
5169 goto out;
5170 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005171 free(curproxy->conf.uniqueid_format_string);
5172 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005173
Willy Tarreau62a61232013-04-12 18:13:46 +02005174 free(curproxy->conf.uif_file);
5175 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5176 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005177 }
William Lallemanda73203e2012-03-12 12:48:57 +01005178
5179 else if (strcmp(args[0], "unique-id-header") == 0) {
5180 if (!*(args[1])) {
5181 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
5184 }
5185 free(curproxy->header_unique_id);
5186 curproxy->header_unique_id = strdup(args[1]);
5187 }
5188
William Lallemand723b73a2012-02-08 16:37:49 +01005189 else if (strcmp(args[0], "log-format") == 0) {
5190 if (!*(args[1])) {
5191 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
5194 }
William Lallemand3203ff42012-11-11 17:30:56 +01005195 if (*(args[2])) {
5196 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
5199 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005200
Willy Tarreau62a61232013-04-12 18:13:46 +02005201 if (curproxy->conf.logformat_string != default_http_log_format &&
5202 curproxy->conf.logformat_string != default_tcp_log_format &&
5203 curproxy->conf.logformat_string != clf_http_log_format)
5204 free(curproxy->conf.logformat_string);
5205 curproxy->conf.logformat_string = strdup(args[1]);
5206
5207 free(curproxy->conf.lfs_file);
5208 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5209 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005210
5211 /* get a chance to improve log-format error reporting by
5212 * reporting the correct line-number when possible.
5213 */
5214 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5215 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5216 file, linenum, curproxy->id);
5217 err_code |= ERR_WARN;
5218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005219 }
William Lallemand723b73a2012-02-08 16:37:49 +01005220
William Lallemand0f99e342011-10-12 17:50:54 +02005221 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5222 /* delete previous herited or defined syslog servers */
5223 struct logsrv *back;
5224
5225 if (*(args[1]) != 0) {
5226 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
5229 }
5230
William Lallemand723b73a2012-02-08 16:37:49 +01005231 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5232 LIST_DEL(&tmplogsrv->list);
5233 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005234 }
5235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005237 struct logsrv *logsrv;
5238
Willy Tarreaubaaee002006-06-26 02:48:02 +02005239 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005240 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005241 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005242 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005243 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005244 LIST_INIT(&node->list);
5245 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 }
5248 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005249 struct sockaddr_storage *sk;
5250 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005251
5252 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005253
William Lallemand0f99e342011-10-12 17:50:54 +02005254 logsrv->facility = get_log_facility(args[2]);
5255 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005256 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005257 err_code |= ERR_ALERT | ERR_FATAL;
5258 goto out;
5259
Willy Tarreaubaaee002006-06-26 02:48:02 +02005260 }
5261
William Lallemand0f99e342011-10-12 17:50:54 +02005262 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005264 logsrv->level = get_log_level(args[3]);
5265 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005267 err_code |= ERR_ALERT | ERR_FATAL;
5268 goto out;
5269
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 }
5271 }
5272
William Lallemand0f99e342011-10-12 17:50:54 +02005273 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005274 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005275 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005276 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005277 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005278 err_code |= ERR_ALERT | ERR_FATAL;
5279 goto out;
5280
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005281 }
5282 }
5283
Willy Tarreau902636f2013-03-10 19:44:48 +01005284 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005285 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005286 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005287 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005288 goto out;
5289 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005290
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005291 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005292
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005293 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005294 if (port1 != port2) {
5295 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5296 file, linenum, args[0], args[1]);
5297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
5299 }
5300
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005301 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005302 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005303 }
William Lallemand0f99e342011-10-12 17:50:54 +02005304
5305 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 }
5307 else {
5308 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5309 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
5313 }
5314 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005315 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005316 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005317 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005318 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005319
Willy Tarreau977b8e42006-12-29 14:19:17 +01005320 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005321 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005322
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005324 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5325 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005329
5330 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005331 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5332 free(curproxy->conn_src.iface_name);
5333 curproxy->conn_src.iface_name = NULL;
5334 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005335
Willy Tarreau902636f2013-03-10 19:44:48 +01005336 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005337 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005338 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005339 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005340 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005341 goto out;
5342 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005343
5344 proto = protocol_by_family(sk->ss_family);
5345 if (!proto || !proto->connect) {
5346 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005347 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005351
5352 if (port1 != port2) {
5353 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5354 file, linenum, args[0], args[1]);
5355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
5357 }
5358
Willy Tarreauef9a3602012-12-08 22:29:20 +01005359 curproxy->conn_src.source_addr = *sk;
5360 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005361
5362 cur_arg = 2;
5363 while (*(args[cur_arg])) {
5364 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005365#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5366#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005367 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005368 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5369 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005372 }
5373#endif
5374 if (!*args[cur_arg + 1]) {
5375 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5376 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005377 err_code |= ERR_ALERT | ERR_FATAL;
5378 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005379 }
5380
5381 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005382 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5383 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005384 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005385 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5386 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005387 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5388 char *name, *end;
5389
5390 name = args[cur_arg+1] + 7;
5391 while (isspace(*name))
5392 name++;
5393
5394 end = name;
5395 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5396 end++;
5397
Willy Tarreauef9a3602012-12-08 22:29:20 +01005398 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5399 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5400 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5401 curproxy->conn_src.bind_hdr_len = end - name;
5402 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5403 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5404 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005405
5406 /* now look for an occurrence number */
5407 while (isspace(*end))
5408 end++;
5409 if (*end == ',') {
5410 end++;
5411 name = end;
5412 if (*end == '-')
5413 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005414 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005415 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005416 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005417 }
5418
Willy Tarreauef9a3602012-12-08 22:29:20 +01005419 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005420 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5421 " occurrences values smaller than %d.\n",
5422 file, linenum, MAX_HDR_HISTORY);
5423 err_code |= ERR_ALERT | ERR_FATAL;
5424 goto out;
5425 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005426 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005427 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005428
Willy Tarreau902636f2013-03-10 19:44:48 +01005429 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005430 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005431 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005432 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005433 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005434 goto out;
5435 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005436
5437 proto = protocol_by_family(sk->ss_family);
5438 if (!proto || !proto->connect) {
5439 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5440 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005441 err_code |= ERR_ALERT | ERR_FATAL;
5442 goto out;
5443 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005444
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005445 if (port1 != port2) {
5446 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5447 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
5450 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005451 curproxy->conn_src.tproxy_addr = *sk;
5452 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005453 }
5454 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005455#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005456 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005457#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005458#else /* no TPROXY support */
5459 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005460 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005461 err_code |= ERR_ALERT | ERR_FATAL;
5462 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005463#endif
5464 cur_arg += 2;
5465 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005466 }
5467
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005468 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5469#ifdef SO_BINDTODEVICE
5470 if (!*args[cur_arg + 1]) {
5471 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5472 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005475 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005476 free(curproxy->conn_src.iface_name);
5477 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5478 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005479 global.last_checks |= LSTCHK_NETADM;
5480#else
5481 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5482 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005485#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005486 cur_arg += 2;
5487 continue;
5488 }
5489 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005490 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005491 err_code |= ERR_ALERT | ERR_FATAL;
5492 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005495 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5496 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5497 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005501 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005502 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005503 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5504 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005505 err_code |= ERR_ALERT | ERR_FATAL;
5506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005507 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005508
5509 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005510 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005511 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005512 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 }
5515 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005516 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005517 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005518 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005519 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521 }
5522 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005523 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005524 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005525 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005526 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005528 }
5529 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005530 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005531 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005532 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005533 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 }
5536 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005537 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005538 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005539 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005540 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005542 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005543 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005544 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005545 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005546 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005547 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005548 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005549 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005550 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005551 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005552 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005553 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005554 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005555 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005556 }
5557 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005558 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005559 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005560 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005561 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005562 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005565 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5567 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005570 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005571
5572 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005573 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005574 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005575 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 }
5578 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005579 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005580 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005581 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005582 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 }
5585 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005586 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005587 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005588 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005589 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 }
5592 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005593 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005594 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005595 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005596 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 }
5599 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005600 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005601 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005602 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005603 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005606 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005607 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005608 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005609 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005610 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005611 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005614 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005615
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 if (curproxy == &defproxy) {
5617 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005621 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005622 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624 if (*(args[1]) == 0) {
5625 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005629
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005630 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005631 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5632 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5633 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005634 err_code |= ERR_ALERT | ERR_FATAL;
5635 goto out;
5636 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005637 err_code |= warnif_cond_conflicts(cond,
5638 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5639 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005640 }
5641 else if (*args[2]) {
5642 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5643 file, linenum, args[0], args[2]);
5644 err_code |= ERR_ALERT | ERR_FATAL;
5645 goto out;
5646 }
5647
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005648 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005649 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005650 wl->s = strdup(args[1]);
5651 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005652 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 }
5654 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005655 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005656 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5657 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005658 err_code |= ERR_ALERT | ERR_FATAL;
5659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005661
Willy Tarreauade5ec42010-01-28 19:33:49 +01005662 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005663 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005664 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005665 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005667 }
5668 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005669 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005670 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005671 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005672 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 }
5675 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005676 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005677 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005678 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005679 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 }
5682 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005683 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5685 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 }
5689
Willy Tarreauade5ec42010-01-28 19:33:49 +01005690 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005691 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005692 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005693 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 }
5696 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005697 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005698 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005699 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005700 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 }
5703 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005704 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005705 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005706 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005707 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 }
5710 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005711 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005712
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 if (curproxy == &defproxy) {
5714 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005718 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005719 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720
Willy Tarreaubaaee002006-06-26 02:48:02 +02005721 if (*(args[1]) == 0) {
5722 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005723 err_code |= ERR_ALERT | ERR_FATAL;
5724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005725 }
5726
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005727 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005728 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5729 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5730 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005731 err_code |= ERR_ALERT | ERR_FATAL;
5732 goto out;
5733 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005734 err_code |= warnif_cond_conflicts(cond,
5735 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5736 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005737 }
5738 else if (*args[2]) {
5739 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5740 file, linenum, args[0], args[2]);
5741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
5743 }
5744
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005745 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005746 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005747 wl->s = strdup(args[1]);
5748 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 }
5750 else if (!strcmp(args[0], "errorloc") ||
5751 !strcmp(args[0], "errorloc302") ||
5752 !strcmp(args[0], "errorloc303")) { /* error location */
5753 int errnum, errlen;
5754 char *err;
5755
Willy Tarreau977b8e42006-12-29 14:19:17 +01005756 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005757 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005758
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005760 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763 }
5764
5765 errnum = atol(args[1]);
5766 if (!strcmp(args[0], "errorloc303")) {
5767 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5768 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5769 } else {
5770 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5771 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5772 }
5773
Willy Tarreau0f772532006-12-23 20:51:41 +01005774 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5775 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005776 chunk_destroy(&curproxy->errmsg[rc]);
5777 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005778 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005779 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005781
5782 if (rc >= HTTP_ERR_SIZE) {
5783 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5784 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 free(err);
5786 }
5787 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005788 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5789 int errnum, errlen, fd;
5790 char *err;
5791 struct stat stat;
5792
5793 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005794 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005795
5796 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005797 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005800 }
5801
5802 fd = open(args[2], O_RDONLY);
5803 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5804 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5805 file, linenum, args[2], args[1]);
5806 if (fd >= 0)
5807 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005808 err_code |= ERR_ALERT | ERR_FATAL;
5809 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005810 }
5811
Willy Tarreau27a674e2009-08-17 07:23:33 +02005812 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005813 errlen = stat.st_size;
5814 } else {
5815 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005816 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005817 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005818 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005819 }
5820
5821 err = malloc(errlen); /* malloc() must succeed during parsing */
5822 errnum = read(fd, err, errlen);
5823 if (errnum != errlen) {
5824 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5825 file, linenum, args[2], args[1]);
5826 close(fd);
5827 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005828 err_code |= ERR_ALERT | ERR_FATAL;
5829 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005830 }
5831 close(fd);
5832
5833 errnum = atol(args[1]);
5834 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5835 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005836 chunk_destroy(&curproxy->errmsg[rc]);
5837 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005838 break;
5839 }
5840 }
5841
5842 if (rc >= HTTP_ERR_SIZE) {
5843 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5844 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005845 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005846 free(err);
5847 }
5848 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005849 else if (!strcmp(args[0], "compression")) {
5850 struct comp *comp;
5851 if (curproxy->comp == NULL) {
5852 comp = calloc(1, sizeof(struct comp));
5853 curproxy->comp = comp;
5854 } else {
5855 comp = curproxy->comp;
5856 }
5857
5858 if (!strcmp(args[1], "algo")) {
5859 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005860 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005861
William Lallemand82fe75c2012-10-23 10:25:10 +02005862 cur_arg = 2;
5863 if (!*args[cur_arg]) {
5864 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5865 file, linenum, args[0]);
5866 err_code |= ERR_ALERT | ERR_FATAL;
5867 goto out;
5868 }
5869 while (*(args[cur_arg])) {
5870 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5871 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5872 file, linenum, args[0], args[cur_arg]);
5873 err_code |= ERR_ALERT | ERR_FATAL;
5874 goto out;
5875 }
William Lallemand552df672012-11-07 13:21:47 +01005876 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5877 curproxy->comp->algos->end(&ctx);
5878 } else {
5879 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5880 file, linenum, args[0], args[cur_arg]);
5881 err_code |= ERR_ALERT | ERR_FATAL;
5882 goto out;
5883 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005884 cur_arg ++;
5885 continue;
5886 }
5887 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005888 else if (!strcmp(args[1], "offload")) {
5889 comp->offload = 1;
5890 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005891 else if (!strcmp(args[1], "type")) {
5892 int cur_arg;
5893 cur_arg = 2;
5894 if (!*args[cur_arg]) {
5895 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5896 file, linenum, args[0]);
5897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
5899 }
5900 while (*(args[cur_arg])) {
5901 comp_append_type(comp, args[cur_arg]);
5902 cur_arg ++;
5903 continue;
5904 }
5905 }
5906 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005907 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005908 file, linenum, args[0]);
5909 err_code |= ERR_ALERT | ERR_FATAL;
5910 goto out;
5911 }
5912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005913 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005914 struct cfg_kw_list *kwl;
5915 int index;
5916
5917 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5918 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5919 if (kwl->kw[index].section != CFG_LISTEN)
5920 continue;
5921 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5922 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005923 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005924 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005925 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005926 err_code |= ERR_ALERT | ERR_FATAL;
5927 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005928 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005929 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005930 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005931 err_code |= ERR_WARN;
5932 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005933 }
Willy Tarreau93893792009-07-23 13:19:11 +02005934 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005935 }
5936 }
5937 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005938
Willy Tarreau6daf3432008-01-22 16:44:08 +01005939 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005940 err_code |= ERR_ALERT | ERR_FATAL;
5941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005942 }
Willy Tarreau93893792009-07-23 13:19:11 +02005943 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005944 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005945 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005946}
5947
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005948int
5949cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5950{
5951
5952 int err_code = 0;
5953 const char *err;
5954
5955 if (!strcmp(args[0], "userlist")) { /* new userlist */
5956 struct userlist *newul;
5957
5958 if (!*args[1]) {
5959 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5960 file, linenum, args[0]);
5961 err_code |= ERR_ALERT | ERR_FATAL;
5962 goto out;
5963 }
5964
5965 err = invalid_char(args[1]);
5966 if (err) {
5967 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5968 file, linenum, *err, args[0], args[1]);
5969 err_code |= ERR_ALERT | ERR_FATAL;
5970 goto out;
5971 }
5972
5973 for (newul = userlist; newul; newul = newul->next)
5974 if (!strcmp(newul->name, args[1])) {
5975 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5976 file, linenum, args[1]);
5977 err_code |= ERR_WARN;
5978 goto out;
5979 }
5980
5981 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5982 if (!newul) {
5983 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5984 err_code |= ERR_ALERT | ERR_ABORT;
5985 goto out;
5986 }
5987
5988 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5989 newul->name = strdup(args[1]);
5990
5991 if (!newul->groupusers | !newul->name) {
5992 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5993 err_code |= ERR_ALERT | ERR_ABORT;
5994 goto out;
5995 }
5996
5997 newul->next = userlist;
5998 userlist = newul;
5999
6000 } else if (!strcmp(args[0], "group")) { /* new group */
6001 int cur_arg, i;
6002 const char *err;
6003
6004 if (!*args[1]) {
6005 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6006 file, linenum, args[0]);
6007 err_code |= ERR_ALERT | ERR_FATAL;
6008 goto out;
6009 }
6010
6011 err = invalid_char(args[1]);
6012 if (err) {
6013 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6014 file, linenum, *err, args[0], args[1]);
6015 err_code |= ERR_ALERT | ERR_FATAL;
6016 goto out;
6017 }
6018
6019 for(i = 0; i < userlist->grpcnt; i++)
6020 if (!strcmp(userlist->groups[i], args[1])) {
6021 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6022 file, linenum, args[1], userlist->name);
6023 err_code |= ERR_ALERT;
6024 goto out;
6025 }
6026
6027 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6028 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6029 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6030 err_code |= ERR_ALERT | ERR_FATAL;
6031 goto out;
6032 }
6033
6034 cur_arg = 2;
6035
6036 while (*args[cur_arg]) {
6037 if (!strcmp(args[cur_arg], "users")) {
6038 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6039 cur_arg += 2;
6040 continue;
6041 } else {
6042 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6043 file, linenum, args[0]);
6044 err_code |= ERR_ALERT | ERR_FATAL;
6045 goto out;
6046 }
6047 }
6048
6049 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6050 } else if (!strcmp(args[0], "user")) { /* new user */
6051 struct auth_users *newuser;
6052 int cur_arg;
6053
6054 if (!*args[1]) {
6055 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6056 file, linenum, args[0]);
6057 err_code |= ERR_ALERT | ERR_FATAL;
6058 goto out;
6059 }
6060
6061 for (newuser = userlist->users; newuser; newuser = newuser->next)
6062 if (!strcmp(newuser->user, args[1])) {
6063 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6064 file, linenum, args[1], userlist->name);
6065 err_code |= ERR_ALERT;
6066 goto out;
6067 }
6068
6069 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6070 if (!newuser) {
6071 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6072 err_code |= ERR_ALERT | ERR_ABORT;
6073 goto out;
6074 }
6075
6076 newuser->user = strdup(args[1]);
6077
6078 newuser->next = userlist->users;
6079 userlist->users = newuser;
6080
6081 cur_arg = 2;
6082
6083 while (*args[cur_arg]) {
6084 if (!strcmp(args[cur_arg], "password")) {
6085#ifndef CONFIG_HAP_CRYPT
6086 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6087 file, linenum);
6088 err_code |= ERR_ALERT;
6089#endif
6090 newuser->pass = strdup(args[cur_arg + 1]);
6091 cur_arg += 2;
6092 continue;
6093 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6094 newuser->pass = strdup(args[cur_arg + 1]);
6095 newuser->flags |= AU_O_INSECURE;
6096 cur_arg += 2;
6097 continue;
6098 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006099 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006100 cur_arg += 2;
6101 continue;
6102 } else {
6103 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6104 file, linenum, args[0]);
6105 err_code |= ERR_ALERT | ERR_FATAL;
6106 goto out;
6107 }
6108 }
6109 } else {
6110 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6111 err_code |= ERR_ALERT | ERR_FATAL;
6112 }
6113
6114out:
6115 return err_code;
6116}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006117
6118/*
6119 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006120 * Returns the error code, 0 if OK, or any combination of :
6121 * - ERR_ABORT: must abort ASAP
6122 * - ERR_FATAL: we can continue parsing but not start the service
6123 * - ERR_WARN: a warning has been emitted
6124 * - ERR_ALERT: an alert has been emitted
6125 * Only the two first ones can stop processing, the two others are just
6126 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006127 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006128int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006129{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006130 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006131 FILE *f;
6132 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006133 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006134 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135
Willy Tarreaubaaee002006-06-26 02:48:02 +02006136 if ((f=fopen(file,"r")) == NULL)
6137 return -1;
6138
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006139 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006140 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006141 char *end;
6142 char *args[MAX_LINE_ARGS + 1];
6143 char *line = thisline;
6144
Willy Tarreaubaaee002006-06-26 02:48:02 +02006145 linenum++;
6146
6147 end = line + strlen(line);
6148
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006149 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6150 /* Check if we reached the limit and the last char is not \n.
6151 * Watch out for the last line without the terminating '\n'!
6152 */
6153 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006154 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006155 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006156 }
6157
Willy Tarreaubaaee002006-06-26 02:48:02 +02006158 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006159 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 line++;
6161
6162 arg = 0;
6163 args[arg] = line;
6164
6165 while (*line && arg < MAX_LINE_ARGS) {
6166 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6167 * C equivalent value. Other combinations left unchanged (eg: \1).
6168 */
6169 if (*line == '\\') {
6170 int skip = 0;
6171 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6172 *line = line[1];
6173 skip = 1;
6174 }
6175 else if (line[1] == 'r') {
6176 *line = '\r';
6177 skip = 1;
6178 }
6179 else if (line[1] == 'n') {
6180 *line = '\n';
6181 skip = 1;
6182 }
6183 else if (line[1] == 't') {
6184 *line = '\t';
6185 skip = 1;
6186 }
6187 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006188 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006189 unsigned char hex1, hex2;
6190 hex1 = toupper(line[2]) - '0';
6191 hex2 = toupper(line[3]) - '0';
6192 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6193 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6194 *line = (hex1<<4) + hex2;
6195 skip = 3;
6196 }
6197 else {
6198 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006199 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006200 }
6201 }
6202 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006203 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006204 end -= skip;
6205 }
6206 line++;
6207 }
6208 else if (*line == '#' || *line == '\n' || *line == '\r') {
6209 /* end of string, end of loop */
6210 *line = 0;
6211 break;
6212 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006213 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006214 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006215 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006216 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006217 line++;
6218 args[++arg] = line;
6219 }
6220 else {
6221 line++;
6222 }
6223 }
6224
6225 /* empty line */
6226 if (!**args)
6227 continue;
6228
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006229 if (*line) {
6230 /* we had to stop due to too many args.
6231 * Let's terminate the string, print the offending part then cut the
6232 * last arg.
6233 */
6234 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6235 line++;
6236 *line = '\0';
6237
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006238 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006239 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006240 err_code |= ERR_ALERT | ERR_FATAL;
6241 args[arg] = line;
6242 }
6243
Willy Tarreau540abe42007-05-02 20:50:16 +02006244 /* zero out remaining args and ensure that at least one entry
6245 * is zeroed out.
6246 */
6247 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006248 args[arg] = line;
6249 }
6250
Willy Tarreau3842f002009-06-14 11:39:52 +02006251 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006252 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006253 char *tmp;
6254
Willy Tarreau3842f002009-06-14 11:39:52 +02006255 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006256 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006257 for (arg=0; *args[arg+1]; arg++)
6258 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006259 *tmp = '\0'; // fix the next arg to \0
6260 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006261 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006262 else if (!strcmp(args[0], "default")) {
6263 kwm = KWM_DEF;
6264 for (arg=0; *args[arg+1]; arg++)
6265 args[arg] = args[arg+1]; // shift args after inversion
6266 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006267
William Lallemand0f99e342011-10-12 17:50:54 +02006268 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6269 strcmp(args[0], "log") != 0) {
6270 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006271 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006272 }
6273
Willy Tarreau977b8e42006-12-29 14:19:17 +01006274 if (!strcmp(args[0], "listen") ||
6275 !strcmp(args[0], "frontend") ||
6276 !strcmp(args[0], "backend") ||
6277 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006278 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006279 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006280 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006281 cursection = strdup(args[0]);
6282 }
6283 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006284 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006285 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006286 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006287 }
6288 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006289 confsect = CFG_USERLIST;
6290 free(cursection);
6291 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006292 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006293 else if (!strcmp(args[0], "peers")) {
6294 confsect = CFG_PEERS;
6295 free(cursection);
6296 cursection = strdup(args[0]);
6297 }
6298
Willy Tarreaubaaee002006-06-26 02:48:02 +02006299 /* else it's a section keyword */
6300
6301 switch (confsect) {
6302 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006303 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006304 break;
6305 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006306 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006307 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006308 case CFG_USERLIST:
6309 err_code |= cfg_parse_users(file, linenum, args, kwm);
6310 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006311 case CFG_PEERS:
6312 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6313 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006314 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006315 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006316 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006317 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006318
6319 if (err_code & ERR_ABORT)
6320 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006321 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006322 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006323 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006325 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006326}
6327
Willy Tarreaubb925012009-07-23 13:36:36 +02006328/*
6329 * Returns the error code, 0 if OK, or any combination of :
6330 * - ERR_ABORT: must abort ASAP
6331 * - ERR_FATAL: we can continue parsing but not start the service
6332 * - ERR_WARN: a warning has been emitted
6333 * - ERR_ALERT: an alert has been emitted
6334 * Only the two first ones can stop processing, the two others are just
6335 * indicators.
6336 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006337int check_config_validity()
6338{
6339 int cfgerr = 0;
6340 struct proxy *curproxy = NULL;
6341 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006342 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006343 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006344 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006345 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006347 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 /*
6349 * Now, check for the integrity of all that we have collected.
6350 */
6351
6352 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006353 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006354
Willy Tarreau193b8c62012-11-22 00:17:38 +01006355 if (!global.tune.max_http_hdr)
6356 global.tune.max_http_hdr = MAX_HTTP_HDR;
6357
6358 if (!global.tune.cookie_len)
6359 global.tune.cookie_len = CAPTURE_LEN;
6360
6361 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6362
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006363 /* first, we will invert the proxy list order */
6364 curproxy = NULL;
6365 while (proxy) {
6366 struct proxy *next;
6367
6368 next = proxy->next;
6369 proxy->next = curproxy;
6370 curproxy = proxy;
6371 if (!next)
6372 break;
6373 proxy = next;
6374 }
6375
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006377 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006378 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006379 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006380 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006381 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006382 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006383 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006384
Willy Tarreau050536d2012-10-04 08:47:34 +02006385 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006386 /* proxy ID not set, use automatic numbering with first
6387 * spare entry starting with next_pxid.
6388 */
6389 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6390 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6391 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006392 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006393 next_pxid++;
6394
Willy Tarreau55ea7572007-06-17 19:56:27 +02006395
Willy Tarreaubaaee002006-06-26 02:48:02 +02006396 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006397 /* ensure we don't keep listeners uselessly bound */
6398 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 curproxy = curproxy->next;
6400 continue;
6401 }
6402
Willy Tarreau16a21472012-11-19 12:39:59 +01006403 /* number of processes this proxy is bound to */
6404 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6405
Willy Tarreauff01a212009-03-15 13:46:16 +01006406 switch (curproxy->mode) {
6407 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006408 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006409 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006410 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6411 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006412 cfgerr++;
6413 }
6414
6415 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006416 Warning("config : servers will be ignored for %s '%s'.\n",
6417 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006418 break;
6419
6420 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006421 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006422 break;
6423
6424 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006425 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006426 break;
6427 }
6428
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006429 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006430 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006431 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006432 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6433 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006434 cfgerr++;
6435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006436#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006437 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006438 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6439 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006440 cfgerr++;
6441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006442#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006443 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006444 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6445 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006446 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006447 }
6448 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006449 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006450 /* If no LB algo is set in a backend, and we're not in
6451 * transparent mode, dispatch mode nor proxy mode, we
6452 * want to use balance roundrobin by default.
6453 */
6454 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6455 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 }
6457 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006458
Willy Tarreau1620ec32011-08-06 17:05:02 +02006459 if (curproxy->options & PR_O_DISPATCH)
6460 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6461 else if (curproxy->options & PR_O_HTTP_PROXY)
6462 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6463 else if (curproxy->options & PR_O_TRANSP)
6464 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006465
Willy Tarreau1620ec32011-08-06 17:05:02 +02006466 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6467 if (curproxy->options & PR_O_DISABLE404) {
6468 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6469 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6470 err_code |= ERR_WARN;
6471 curproxy->options &= ~PR_O_DISABLE404;
6472 }
6473 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6474 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6475 "send-state", proxy_type_str(curproxy), curproxy->id);
6476 err_code |= ERR_WARN;
6477 curproxy->options &= ~PR_O2_CHK_SNDST;
6478 }
Willy Tarreauef781042010-01-27 11:53:01 +01006479 }
6480
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006481 /* if a default backend was specified, let's find it */
6482 if (curproxy->defbe.name) {
6483 struct proxy *target;
6484
Alex Williams96532db2009-11-01 21:27:13 -05006485 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006486 if (!target) {
6487 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6488 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006489 cfgerr++;
6490 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006491 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6492 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006493 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006494 } else {
6495 free(curproxy->defbe.name);
6496 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006497 /* we force the backend to be present on at least all of
6498 * the frontend's processes.
6499 */
6500 target->bind_proc = curproxy->bind_proc ?
6501 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006502
6503 /* Emit a warning if this proxy also has some servers */
6504 if (curproxy->srv) {
6505 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6506 curproxy->id);
6507 err_code |= ERR_WARN;
6508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 }
6510 }
6511
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006512 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006513 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6514 /* map jump target for ACT_SETBE in req_rep chain */
6515 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006516 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006517 struct proxy *target;
6518
Willy Tarreaua496b602006-12-17 23:15:24 +01006519 if (exp->action != ACT_SETBE)
6520 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006521
Alex Williams96532db2009-11-01 21:27:13 -05006522 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006523 if (!target) {
6524 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6525 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006526 cfgerr++;
6527 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006528 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6529 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006530 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006531 } else {
6532 free((void *)exp->replace);
6533 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006534 /* we force the backend to be present on at least all of
6535 * the frontend's processes.
6536 */
6537 target->bind_proc = curproxy->bind_proc ?
6538 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006539 }
6540 }
6541 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006542
6543 /* find the target proxy for 'use_backend' rules */
6544 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006545 struct proxy *target;
6546
Alex Williams96532db2009-11-01 21:27:13 -05006547 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006548
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006549 if (!target) {
6550 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6551 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006552 cfgerr++;
6553 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006554 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6555 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006556 cfgerr++;
6557 } else {
6558 free((void *)rule->be.name);
6559 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006560 /* we force the backend to be present on at least all of
6561 * the frontend's processes.
6562 */
6563 target->bind_proc = curproxy->bind_proc ?
6564 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006565 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006566 }
6567
6568 /* find the target proxy for 'use_backend' rules */
6569 list_for_each_entry(srule, &curproxy->server_rules, list) {
6570 struct server *target = findserver(curproxy, srule->srv.name);
6571
6572 if (!target) {
6573 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6574 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6575 cfgerr++;
6576 continue;
6577 }
6578 free((void *)srule->srv.name);
6579 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006580 }
6581
Emeric Brunb982a3d2010-01-04 15:45:53 +01006582 /* find the target table for 'stick' rules */
6583 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6584 struct proxy *target;
6585
Emeric Brun1d33b292010-01-04 15:47:17 +01006586 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6587 if (mrule->flags & STK_IS_STORE)
6588 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6589
Emeric Brunb982a3d2010-01-04 15:45:53 +01006590 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006591 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006592 else
6593 target = curproxy;
6594
6595 if (!target) {
6596 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6597 curproxy->id, mrule->table.name);
6598 cfgerr++;
6599 }
6600 else if (target->table.size == 0) {
6601 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6602 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6603 cfgerr++;
6604 }
Willy Tarreau12785782012-04-27 21:37:17 +02006605 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6606 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006607 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6608 cfgerr++;
6609 }
6610 else {
6611 free((void *)mrule->table.name);
6612 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006613 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006614 }
6615 }
6616
6617 /* find the target table for 'store response' rules */
6618 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6619 struct proxy *target;
6620
Emeric Brun1d33b292010-01-04 15:47:17 +01006621 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6622
Emeric Brunb982a3d2010-01-04 15:45:53 +01006623 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006624 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006625 else
6626 target = curproxy;
6627
6628 if (!target) {
6629 Alert("Proxy '%s': unable to find store table '%s'.\n",
6630 curproxy->id, mrule->table.name);
6631 cfgerr++;
6632 }
6633 else if (target->table.size == 0) {
6634 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6635 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6636 cfgerr++;
6637 }
Willy Tarreau12785782012-04-27 21:37:17 +02006638 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6639 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006640 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6641 cfgerr++;
6642 }
6643 else {
6644 free((void *)mrule->table.name);
6645 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006646 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006647 }
6648 }
6649
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006650 /* find the target table for 'tcp-request' layer 4 rules */
6651 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6652 struct proxy *target;
6653
Willy Tarreaub4c84932013-07-23 19:15:30 +02006654 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006655 continue;
6656
6657 if (trule->act_prm.trk_ctr.table.n)
6658 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6659 else
6660 target = curproxy;
6661
6662 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006663 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6664 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006665 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006666 cfgerr++;
6667 }
6668 else if (target->table.size == 0) {
6669 Alert("Proxy '%s': table '%s' used but not configured.\n",
6670 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6671 cfgerr++;
6672 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006673 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6674 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6675 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006676 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006677 cfgerr++;
6678 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006679 else {
6680 free(trule->act_prm.trk_ctr.table.n);
6681 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006682 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006683 * to pass a list of counters to track and allocate them right here using
6684 * stktable_alloc_data_type().
6685 */
6686 }
6687 }
6688
Willy Tarreaud1f96522010-08-03 19:34:32 +02006689 /* find the target table for 'tcp-request' layer 6 rules */
6690 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6691 struct proxy *target;
6692
Willy Tarreaub4c84932013-07-23 19:15:30 +02006693 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006694 continue;
6695
6696 if (trule->act_prm.trk_ctr.table.n)
6697 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6698 else
6699 target = curproxy;
6700
6701 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006702 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6703 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006704 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006705 cfgerr++;
6706 }
6707 else if (target->table.size == 0) {
6708 Alert("Proxy '%s': table '%s' used but not configured.\n",
6709 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6710 cfgerr++;
6711 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006712 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6713 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6714 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006715 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006716 cfgerr++;
6717 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006718 else {
6719 free(trule->act_prm.trk_ctr.table.n);
6720 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006721 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006722 * to pass a list of counters to track and allocate them right here using
6723 * stktable_alloc_data_type().
6724 */
6725 }
6726 }
6727
Emeric Brun32da3c42010-09-23 18:39:19 +02006728 if (curproxy->table.peers.name) {
6729 struct peers *curpeers = peers;
6730
6731 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6732 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6733 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006734 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006735 break;
6736 }
6737 }
6738
6739 if (!curpeers) {
6740 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6741 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006742 free((void *)curproxy->table.peers.name);
6743 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006744 cfgerr++;
6745 }
6746 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006747 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6748 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006749 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006750 cfgerr++;
6751 }
6752 }
6753
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006754 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006755 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006756 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6757 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6758 "proxy", curproxy->id);
6759 cfgerr++;
6760 goto out_uri_auth_compat;
6761 }
6762
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006763 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006764 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006765 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006766 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006767
Willy Tarreau95fa4692010-02-01 13:05:50 +01006768 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6769 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006770
6771 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006772 uri_auth_compat_req[i++] = "realm";
6773 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6774 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006775
Willy Tarreau95fa4692010-02-01 13:05:50 +01006776 uri_auth_compat_req[i++] = "unless";
6777 uri_auth_compat_req[i++] = "{";
6778 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6779 uri_auth_compat_req[i++] = "}";
6780 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006781
Willy Tarreauff011f22011-01-06 17:51:27 +01006782 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6783 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006784 cfgerr++;
6785 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006786 }
6787
Willy Tarreauff011f22011-01-06 17:51:27 +01006788 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006789
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006790 if (curproxy->uri_auth->auth_realm) {
6791 free(curproxy->uri_auth->auth_realm);
6792 curproxy->uri_auth->auth_realm = NULL;
6793 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006794
6795 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006796 }
6797out_uri_auth_compat:
6798
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006799 /* compile the log format */
6800 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006801 if (curproxy->conf.logformat_string != default_http_log_format &&
6802 curproxy->conf.logformat_string != default_tcp_log_format &&
6803 curproxy->conf.logformat_string != clf_http_log_format)
6804 free(curproxy->conf.logformat_string);
6805 curproxy->conf.logformat_string = NULL;
6806 free(curproxy->conf.lfs_file);
6807 curproxy->conf.lfs_file = NULL;
6808 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006809 }
6810
Willy Tarreau62a61232013-04-12 18:13:46 +02006811 if (curproxy->conf.logformat_string) {
6812 curproxy->conf.args.ctx = ARGC_LOG;
6813 curproxy->conf.args.file = curproxy->conf.lfs_file;
6814 curproxy->conf.args.line = curproxy->conf.lfs_line;
6815 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006816 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006817 curproxy->conf.args.file = NULL;
6818 curproxy->conf.args.line = 0;
6819 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006820
Willy Tarreau62a61232013-04-12 18:13:46 +02006821 if (curproxy->conf.uniqueid_format_string) {
6822 curproxy->conf.args.ctx = ARGC_UIF;
6823 curproxy->conf.args.file = curproxy->conf.uif_file;
6824 curproxy->conf.args.line = curproxy->conf.uif_line;
6825 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006826 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006827 curproxy->conf.args.file = NULL;
6828 curproxy->conf.args.line = 0;
6829 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006830
6831 /* only now we can check if some args remain unresolved */
6832 cfgerr += smp_resolve_args(curproxy);
6833 if (!cfgerr)
6834 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006835
Willy Tarreau2738a142006-07-08 17:28:09 +02006836 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006837 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006838 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006839 (!curproxy->timeout.connect ||
6840 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006841 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006842 " | While not properly invalid, you will certainly encounter various problems\n"
6843 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006844 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006845 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006846 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006847 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006848
Willy Tarreau1fa31262007-12-03 00:36:16 +01006849 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6850 * We must still support older configurations, so let's find out whether those
6851 * parameters have been set or must be copied from contimeouts.
6852 */
6853 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006854 if (!curproxy->timeout.tarpit ||
6855 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006856 /* tarpit timeout not set. We search in the following order:
6857 * default.tarpit, curr.connect, default.connect.
6858 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006859 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006860 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006861 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006862 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006863 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006864 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006865 }
6866 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006867 (!curproxy->timeout.queue ||
6868 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006869 /* queue timeout not set. We search in the following order:
6870 * default.queue, curr.connect, default.connect.
6871 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006872 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006873 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006874 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006875 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006876 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006877 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006878 }
6879 }
6880
Willy Tarreau1620ec32011-08-06 17:05:02 +02006881 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006882 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6883 curproxy->check_req = (char *)malloc(curproxy->check_len);
6884 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006885 }
6886
Willy Tarreau193b8c62012-11-22 00:17:38 +01006887 /* ensure that cookie capture length is not too large */
6888 if (curproxy->capture_len >= global.tune.cookie_len) {
6889 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6890 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6891 err_code |= ERR_WARN;
6892 curproxy->capture_len = global.tune.cookie_len - 1;
6893 }
6894
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006895 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006896 if (curproxy->nb_req_cap) {
6897 if (curproxy->mode == PR_MODE_HTTP) {
6898 curproxy->req_cap_pool = create_pool("ptrcap",
6899 curproxy->nb_req_cap * sizeof(char *),
6900 MEM_F_SHARED);
6901 } else {
6902 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6903 proxy_type_str(curproxy), curproxy->id);
6904 err_code |= ERR_WARN;
6905 curproxy->to_log &= ~LW_REQHDR;
6906 curproxy->nb_req_cap = 0;
6907 }
6908 }
6909
6910 if (curproxy->nb_rsp_cap) {
6911 if (curproxy->mode == PR_MODE_HTTP) {
6912 curproxy->rsp_cap_pool = create_pool("ptrcap",
6913 curproxy->nb_rsp_cap * sizeof(char *),
6914 MEM_F_SHARED);
6915 } else {
6916 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6917 proxy_type_str(curproxy), curproxy->id);
6918 err_code |= ERR_WARN;
6919 curproxy->to_log &= ~LW_REQHDR;
6920 curproxy->nb_rsp_cap = 0;
6921 }
6922 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006923
Willy Tarreaubaaee002006-06-26 02:48:02 +02006924 /* first, we will invert the servers list order */
6925 newsrv = NULL;
6926 while (curproxy->srv) {
6927 struct server *next;
6928
6929 next = curproxy->srv->next;
6930 curproxy->srv->next = newsrv;
6931 newsrv = curproxy->srv;
6932 if (!next)
6933 break;
6934 curproxy->srv = next;
6935 }
6936
Willy Tarreaudd701652010-05-25 23:03:02 +02006937 /* assign automatic UIDs to servers which don't have one yet */
6938 next_id = 1;
6939 newsrv = curproxy->srv;
6940 while (newsrv != NULL) {
6941 if (!newsrv->puid) {
6942 /* server ID not set, use automatic numbering with first
6943 * spare entry starting with next_svid.
6944 */
6945 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6946 newsrv->conf.id.key = newsrv->puid = next_id;
6947 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6948 }
6949 next_id++;
6950 newsrv = newsrv->next;
6951 }
6952
Willy Tarreau20697042007-11-15 23:26:18 +01006953 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006954 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006955
Willy Tarreau62c3be22012-01-20 13:12:32 +01006956 /*
6957 * If this server supports a maxconn parameter, it needs a dedicated
6958 * tasks to fill the emptied slots when a connection leaves.
6959 * Also, resolve deferred tracking dependency if needed.
6960 */
6961 newsrv = curproxy->srv;
6962 while (newsrv != NULL) {
6963 if (newsrv->minconn > newsrv->maxconn) {
6964 /* Only 'minconn' was specified, or it was higher than or equal
6965 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6966 * this will avoid further useless expensive computations.
6967 */
6968 newsrv->maxconn = newsrv->minconn;
6969 } else if (newsrv->maxconn && !newsrv->minconn) {
6970 /* minconn was not specified, so we set it to maxconn */
6971 newsrv->minconn = newsrv->maxconn;
6972 }
6973
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006974#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006975 if (newsrv->use_ssl || newsrv->check.use_ssl)
6976 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006977#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006978
Willy Tarreau2f075e92013-12-03 11:11:34 +01006979 /* set the check type on the server */
6980 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6981
Willy Tarreau62c3be22012-01-20 13:12:32 +01006982 if (newsrv->trackit) {
6983 struct proxy *px;
6984 struct server *srv;
6985 char *pname, *sname;
6986
6987 pname = newsrv->trackit;
6988 sname = strrchr(pname, '/');
6989
6990 if (sname)
6991 *sname++ = '\0';
6992 else {
6993 sname = pname;
6994 pname = NULL;
6995 }
6996
6997 if (pname) {
6998 px = findproxy(pname, PR_CAP_BE);
6999 if (!px) {
7000 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7001 proxy_type_str(curproxy), curproxy->id,
7002 newsrv->id, pname);
7003 cfgerr++;
7004 goto next_srv;
7005 }
7006 } else
7007 px = curproxy;
7008
7009 srv = findserver(px, sname);
7010 if (!srv) {
7011 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7012 proxy_type_str(curproxy), curproxy->id,
7013 newsrv->id, sname);
7014 cfgerr++;
7015 goto next_srv;
7016 }
7017
7018 if (!(srv->state & SRV_CHECKED)) {
7019 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7020 "tracking as it does not have checks enabled.\n",
7021 proxy_type_str(curproxy), curproxy->id,
7022 newsrv->id, px->id, srv->id);
7023 cfgerr++;
7024 goto next_srv;
7025 }
7026
7027 if (curproxy != px &&
7028 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7029 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7030 "tracking: disable-on-404 option inconsistency.\n",
7031 proxy_type_str(curproxy), curproxy->id,
7032 newsrv->id, px->id, srv->id);
7033 cfgerr++;
7034 goto next_srv;
7035 }
7036
7037 /* if the other server is forced disabled, we have to do the same here */
7038 if (srv->state & SRV_MAINTAIN) {
7039 newsrv->state |= SRV_MAINTAIN;
7040 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007041 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007042 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007043 }
7044
7045 newsrv->track = srv;
7046 newsrv->tracknext = srv->tracknext;
7047 srv->tracknext = newsrv;
7048
7049 free(newsrv->trackit);
7050 newsrv->trackit = NULL;
7051 }
7052 next_srv:
7053 newsrv = newsrv->next;
7054 }
7055
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007056 /* We have to initialize the server lookup mechanism depending
7057 * on what LB algorithm was choosen.
7058 */
7059
7060 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7061 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7062 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007063 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7064 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7065 init_server_map(curproxy);
7066 } else {
7067 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7068 fwrr_init_server_groups(curproxy);
7069 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007070 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007071
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007072 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007073 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7074 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7075 fwlc_init_server_tree(curproxy);
7076 } else {
7077 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7078 fas_init_server_tree(curproxy);
7079 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007080 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007081
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007082 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007083 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7084 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7085 chash_init_server_tree(curproxy);
7086 } else {
7087 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7088 init_server_map(curproxy);
7089 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007090 break;
7091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007092
7093 if (curproxy->options & PR_O_LOGASAP)
7094 curproxy->to_log &= ~LW_BYTES;
7095
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007096 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007097 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007098 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7099 proxy_type_str(curproxy), curproxy->id);
7100 err_code |= ERR_WARN;
7101 }
7102
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007103 if (curproxy->mode != PR_MODE_HTTP) {
7104 int optnum;
7105
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007106 if (curproxy->uri_auth) {
7107 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7108 proxy_type_str(curproxy), curproxy->id);
7109 err_code |= ERR_WARN;
7110 curproxy->uri_auth = NULL;
7111 }
7112
Willy Tarreau87cf5142011-08-19 22:57:24 +02007113 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007114 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7115 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7116 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007117 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007118 }
7119
7120 if (curproxy->options & PR_O_ORGTO) {
7121 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7122 "originalto", proxy_type_str(curproxy), curproxy->id);
7123 err_code |= ERR_WARN;
7124 curproxy->options &= ~PR_O_ORGTO;
7125 }
7126
7127 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7128 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7129 (curproxy->cap & cfg_opts[optnum].cap) &&
7130 (curproxy->options & cfg_opts[optnum].val)) {
7131 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7132 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7133 err_code |= ERR_WARN;
7134 curproxy->options &= ~cfg_opts[optnum].val;
7135 }
7136 }
7137
7138 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7139 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7140 (curproxy->cap & cfg_opts2[optnum].cap) &&
7141 (curproxy->options2 & cfg_opts2[optnum].val)) {
7142 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7143 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7144 err_code |= ERR_WARN;
7145 curproxy->options2 &= ~cfg_opts2[optnum].val;
7146 }
7147 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007148
Pieter Baauwd551fb52013-05-08 22:49:23 +02007149#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007150 if (curproxy->conn_src.bind_hdr_occ) {
7151 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007152 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007153 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007154 err_code |= ERR_WARN;
7155 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007156#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007157 }
7158
Willy Tarreaubaaee002006-06-26 02:48:02 +02007159 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007160 * ensure that we're not cross-dressing a TCP server into HTTP.
7161 */
7162 newsrv = curproxy->srv;
7163 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007164 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007165 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7166 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007167 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007168 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007169
Willy Tarreau0cec3312011-10-31 13:49:26 +01007170 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7171 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7172 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7173 err_code |= ERR_WARN;
7174 }
7175
Willy Tarreau82ffa392013-08-13 17:19:08 +02007176 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7177 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7178 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7179 err_code |= ERR_WARN;
7180 }
7181
Pieter Baauwd551fb52013-05-08 22:49:23 +02007182#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007183 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7184 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007185 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 +01007186 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007187 err_code |= ERR_WARN;
7188 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007189#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007190 newsrv = newsrv->next;
7191 }
7192
Willy Tarreauc1a21672009-08-16 22:37:44 +02007193 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007194 if (!curproxy->accept)
7195 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007196
Willy Tarreauc1a21672009-08-16 22:37:44 +02007197 if (curproxy->tcp_req.inspect_delay ||
7198 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007199 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007200
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007201 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007202 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007203 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007204 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007205
7206 /* both TCP and HTTP must check switching rules */
7207 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7208 }
7209
7210 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007211 if (curproxy->tcp_req.inspect_delay ||
7212 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7213 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7214
Emeric Brun97679e72010-09-23 17:56:44 +02007215 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7216 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7217
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007218 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007219 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007220 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007221 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007222
7223 /* If the backend does requires RDP cookie persistence, we have to
7224 * enable the corresponding analyser.
7225 */
7226 if (curproxy->options2 & PR_O2_RDPC_PRST)
7227 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7228 }
7229
Emeric Brunc52962f2012-11-15 18:28:02 +01007230#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007231 /* Configure SSL for each bind line.
7232 * Note: if configuration fails at some point, the ->ctx member
7233 * remains NULL so that listeners can later detach.
7234 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007235 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007236 if (!bind_conf->is_ssl) {
7237 if (bind_conf->default_ctx) {
7238 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7239 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7240 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007241 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007242 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007243 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007244 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007245 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007246 cfgerr++;
7247 continue;
7248 }
7249
Emeric Brun4b3091e2012-09-24 15:48:52 +02007250 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007251 Alert("Unable to allocate SSL session cache.\n");
7252 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007253 continue;
7254 }
7255
Emeric Brunfc0421f2012-09-07 17:30:07 +02007256 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007257 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007258 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007259#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007260
Willy Tarreaue6b98942007-10-29 01:09:36 +01007261 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007262 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007263 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007264 if (!listener->luid) {
7265 /* listener ID not set, use automatic numbering with first
7266 * spare entry starting with next_luid.
7267 */
7268 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7269 listener->conf.id.key = listener->luid = next_id;
7270 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007271 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007272 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007273
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007274 /* enable separate counters */
7275 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7276 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007277 if (!listener->name)
7278 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007279 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007280
Willy Tarreaue6b98942007-10-29 01:09:36 +01007281 if (curproxy->options & PR_O_TCP_NOLING)
7282 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007283 if (!listener->maxconn)
7284 listener->maxconn = curproxy->maxconn;
7285 if (!listener->backlog)
7286 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007287 if (!listener->maxaccept)
7288 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7289
7290 /* we want to have an optimal behaviour on single process mode to
7291 * maximize the work at once, but in multi-process we want to keep
7292 * some fairness between processes, so we target half of the max
7293 * number of events to be balanced over all the processes the proxy
7294 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7295 * used to disable the limit.
7296 */
7297 if (listener->maxaccept > 0) {
7298 if (nbproc > 1)
7299 listener->maxaccept = (listener->maxaccept + 1) / 2;
7300 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7301 }
7302
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007303 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007304 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007305 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007306 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007307
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007308 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7309 listener->options |= LI_O_TCP_RULES;
7310
Willy Tarreaude3041d2010-05-31 10:56:17 +02007311 if (curproxy->mon_mask.s_addr)
7312 listener->options |= LI_O_CHK_MONNET;
7313
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007314 /* smart accept mode is automatic in HTTP mode */
7315 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007316 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007317 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7318 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007319 }
7320
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007321 /* Release unused SSL configs */
7322 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7323 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007324 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007325#ifdef USE_OPENSSL
7326 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007327 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007328 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007329 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007330 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007331#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007332 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007333
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007334 /* Check multi-process mode compatibility for the current proxy */
7335 if (global.nbproc > 1) {
7336 int nbproc = 0;
7337 if (curproxy->bind_proc) {
7338 int proc;
7339 for (proc = 0; proc < global.nbproc; proc++) {
7340 if (curproxy->bind_proc & (1 << proc)) {
7341 nbproc++;
7342 }
7343 }
7344 } else {
7345 nbproc = global.nbproc;
7346 }
7347 if (curproxy->table.peers.name) {
7348 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7349 curproxy->id);
7350 cfgerr++;
7351 }
7352 if (nbproc > 1) {
7353 if (curproxy->uri_auth) {
7354 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7355 curproxy->id);
7356 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7357 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7358 curproxy->id);
7359 }
7360 }
7361 if (curproxy->appsession_name) {
7362 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7363 curproxy->id);
7364 }
7365 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7366 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7367 curproxy->id);
7368 }
7369 }
7370 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007371
7372 /* create the task associated with the proxy */
7373 curproxy->task = task_new();
7374 if (curproxy->task) {
7375 curproxy->task->context = curproxy;
7376 curproxy->task->process = manage_proxy;
7377 /* no need to queue, it will be done automatically if some
7378 * listener gets limited.
7379 */
7380 curproxy->task->expire = TICK_ETERNITY;
7381 } else {
7382 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7383 curproxy->id);
7384 cfgerr++;
7385 }
7386
Willy Tarreaubaaee002006-06-26 02:48:02 +02007387 curproxy = curproxy->next;
7388 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007389
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007390 /* Check multi-process mode compatibility */
7391 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007392 if (global.stats_fe && !global.stats_fe->bind_proc) {
7393 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 +01007394 }
7395 }
7396
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007397 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7398 struct auth_users *curuser;
7399 int g;
7400
7401 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7402 unsigned int group_mask = 0;
7403 char *group = NULL;
7404
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007405 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007406 continue;
7407
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007408 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007409
7410 for (g = 0; g < curuserlist->grpcnt; g++)
7411 if (!strcmp(curuserlist->groups[g], group))
7412 break;
7413
7414 if (g == curuserlist->grpcnt) {
7415 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7416 curuserlist->name, group, curuser->user);
7417 err_code |= ERR_ALERT | ERR_FATAL;
7418 goto out;
7419 }
7420
7421 group_mask |= (1 << g);
7422 }
7423
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007424 free(curuser->u.groups);
7425 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007426 }
7427
7428 for (g = 0; g < curuserlist->grpcnt; g++) {
7429 char *user = NULL;
7430
7431 if (!curuserlist->groupusers[g])
7432 continue;
7433
7434 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7435 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7436 if (!strcmp(curuser->user, user))
7437 break;
7438
7439 if (!curuser) {
7440 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7441 curuserlist->name, user, curuserlist->groups[g]);
7442 err_code |= ERR_ALERT | ERR_FATAL;
7443 goto out;
7444 }
7445
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007446 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007447 }
7448
7449 free(curuserlist->groupusers[g]);
7450 }
7451
7452 free(curuserlist->groupusers);
7453
7454#ifdef DEBUG_AUTH
7455 for (g = 0; g < curuserlist->grpcnt; g++) {
7456 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7457
7458 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007459 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007460 fprintf(stderr, " %s", curuser->user);
7461 }
7462
7463 fprintf(stderr, "\n");
7464 }
7465#endif
7466
Willy Tarreaufbb78422011-06-05 15:38:35 +02007467 }
7468
7469 /* automatically compute fullconn if not set. We must not do it in the
7470 * loop above because cross-references are not yet fully resolved.
7471 */
7472 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7473 /* If <fullconn> is not set, let's set it to 10% of the sum of
7474 * the possible incoming frontend's maxconns.
7475 */
7476 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7477 struct proxy *fe;
7478 int total = 0;
7479
7480 /* sum up the number of maxconns of frontends which
7481 * reference this backend at least once or which are
7482 * the same one ('listen').
7483 */
7484 for (fe = proxy; fe; fe = fe->next) {
7485 struct switching_rule *rule;
7486 struct hdr_exp *exp;
7487 int found = 0;
7488
7489 if (!(fe->cap & PR_CAP_FE))
7490 continue;
7491
7492 if (fe == curproxy) /* we're on a "listen" instance */
7493 found = 1;
7494
7495 if (fe->defbe.be == curproxy) /* "default_backend" */
7496 found = 1;
7497
7498 /* check if a "use_backend" rule matches */
7499 if (!found) {
7500 list_for_each_entry(rule, &fe->switching_rules, list) {
7501 if (rule->be.backend == curproxy) {
7502 found = 1;
7503 break;
7504 }
7505 }
7506 }
7507
7508 /* check if a "reqsetbe" rule matches */
7509 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7510 if (exp->action == ACT_SETBE &&
7511 (struct proxy *)exp->replace == curproxy) {
7512 found = 1;
7513 break;
7514 }
7515 }
7516
7517 /* now we've checked all possible ways to reference a backend
7518 * from a frontend.
7519 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007520 if (!found)
7521 continue;
7522 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007523 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007524 /* we have the sum of the maxconns in <total>. We only
7525 * keep 10% of that sum to set the default fullconn, with
7526 * a hard minimum of 1 (to avoid a divide by zero).
7527 */
7528 curproxy->fullconn = (total + 9) / 10;
7529 if (!curproxy->fullconn)
7530 curproxy->fullconn = 1;
7531 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007532 }
7533
Willy Tarreau056f5682010-06-06 15:51:11 +02007534 /* initialize stick-tables on backend capable proxies. This must not
7535 * be done earlier because the data size may be discovered while parsing
7536 * other proxies.
7537 */
7538 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007539 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007540
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007541 /*
7542 * Recount currently required checks.
7543 */
7544
7545 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7546 int optnum;
7547
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007548 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7549 if (curproxy->options & cfg_opts[optnum].val)
7550 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007551
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007552 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7553 if (curproxy->options2 & cfg_opts2[optnum].val)
7554 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007555 }
7556
Willy Tarreau122541c2011-09-07 21:24:49 +02007557 if (peers) {
7558 struct peers *curpeers = peers, **last;
7559 struct peer *p, *pb;
7560
7561 /* Remove all peers sections which don't have a valid listener.
7562 * This can happen when a peers section is never referenced and
7563 * does not contain a local peer.
7564 */
7565 last = &peers;
7566 while (*last) {
7567 curpeers = *last;
7568 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007569 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007570 last = &curpeers->next;
7571 continue;
7572 }
7573
7574 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7575 curpeers->id, localpeer);
7576
7577 p = curpeers->remote;
7578 while (p) {
7579 pb = p->next;
7580 free(p->id);
7581 free(p);
7582 p = pb;
7583 }
7584
7585 /* Destroy and unlink this curpeers section.
7586 * Note: curpeers is backed up into *last.
7587 */
7588 free(curpeers->id);
7589 curpeers = curpeers->next;
7590 free(*last);
7591 *last = curpeers;
7592 }
7593 }
7594
Willy Tarreau34eb6712011-10-24 18:15:04 +02007595 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007596 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007597 MEM_F_SHARED);
7598
Willy Tarreaubb925012009-07-23 13:36:36 +02007599 if (cfgerr > 0)
7600 err_code |= ERR_ALERT | ERR_FATAL;
7601 out:
7602 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007603}
7604
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007605/*
7606 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7607 * parsing sessions.
7608 */
7609void cfg_register_keywords(struct cfg_kw_list *kwl)
7610{
7611 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7612}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007613
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007614/*
7615 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7616 */
7617void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7618{
7619 LIST_DEL(&kwl->list);
7620 LIST_INIT(&kwl->list);
7621}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007622
7623/*
7624 * Local variables:
7625 * c-indent-level: 8
7626 * c-basic-offset: 8
7627 * End:
7628 */