blob: cc515a2058577044d09bdd92bf5c19271a1960f2 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100209 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100210 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
212 str = next;
213 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100214 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 *next++ = 0;
216 }
217
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100218 ss2 = str2sa_range(str, &port, &end, err,
219 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
220 if (!ss2)
221 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100223 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100224 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100229 if (!port || !end) {
230 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
231 goto fail;
232 }
233
Emeric Bruned760922010-10-22 17:59:25 +0200234 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200235 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200236 goto fail;
237 }
238
239 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200240 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 else if (ss2->ss_family == AF_UNSPEC) {
245 socklen_t addr_len;
246
247 /* We want to attach to an already bound fd whose number
248 * is in the addr part of ss2 when cast to sockaddr_in.
249 * Note that by definition there is a single listener.
250 * We still have to determine the address family to
251 * register the correct protocol.
252 */
253 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
254 addr_len = sizeof(*ss2);
255 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
256 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
257 goto fail;
258 }
259
260 port = end = get_host_port(ss2);
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100263 /* OK the address looks correct */
264 ss = *ss2;
265
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100268 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200269 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
270 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
271 l->frontend = curproxy;
272 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273
Willy Tarreau40aa0702013-03-10 23:51:38 +0100274 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200276 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100277 l->state = LI_INIT;
278
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100279 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100281 tcpv4_add_listener(l);
282 }
Emeric Bruned760922010-10-22 17:59:25 +0200283 else if (ss.ss_family == AF_INET6) {
284 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
285 tcpv6_add_listener(l);
286 }
287 else {
Emeric Bruned760922010-10-22 17:59:25 +0200288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100417/* Report it if a request ACL condition uses some keywords that are incompatible
418 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
419 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
420 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100421 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100422static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200425 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100428 return 0;
429
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100430 acl = acl_cond_conflicts(cond, where);
431 if (acl) {
432 if (acl->name && *acl->name)
433 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
434 file, line, acl->name, sample_ckp_names(where));
435 else
436 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200437 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100438 return ERR_WARN;
439 }
440 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100441 return 0;
442
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 if (acl->name && *acl->name)
444 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446 else
447 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200448 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100449 return ERR_WARN;
450}
451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200471 else if (!strcmp(args[0], "ca-base")) {
472#ifdef USE_OPENSSL
473 if (global.ca_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.ca_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
490 else if (!strcmp(args[0], "crt-base")) {
491#ifdef USE_OPENSSL
492 if (global.crt_base != NULL) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.crt_base = strdup(args[1]);
503#else
504 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507#endif
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "daemon")) {
510 global.mode |= MODE_DAEMON;
511 }
512 else if (!strcmp(args[0], "debug")) {
513 global.mode |= MODE_DEBUG;
514 }
515 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200518 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100524 else if (!strcmp(args[0], "nosplice")) {
525 global.tune.options &= ~GTUNE_USE_SPLICE;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "quiet")) {
528 global.mode |= MODE_QUIET;
529 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200530 else if (!strcmp(args[0], "tune.maxpollevents")) {
531 if (global.tune.maxpollevents != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200540 }
541 global.tune.maxpollevents = atol(args[1]);
542 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100543 else if (!strcmp(args[0], "tune.maxaccept")) {
544 if (global.tune.maxaccept != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100553 }
554 global.tune.maxaccept = atol(args[1]);
555 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200556 else if (!strcmp(args[0], "tune.chksize")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.chksize = atol(args[1]);
563 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200564#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100565 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.sslcachesize = atol(args[1]);
572 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100573 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
574 unsigned int ssllifetime;
575 const char *res;
576
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582
583 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
584 if (res) {
585 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
586 file, linenum, *res, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590
591 global.tune.ssllifetime = ssllifetime;
592 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100593 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.ssl_max_record = atol(args[1]);
600 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200602 else if (!strcmp(args[0], "tune.bufsize")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.bufsize = atol(args[1]);
609 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
610 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100611 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200612 }
613 else if (!strcmp(args[0], "tune.maxrewrite")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.maxrewrite = atol(args[1]);
620 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
621 global.tune.maxrewrite = global.tune.bufsize / 2;
622 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100623 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
624 if (global.tune.client_rcvbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_rcvbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
637 if (global.tune.server_rcvbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_rcvbuf = atol(args[1]);
648 }
649 else if (!strcmp(args[0], "tune.sndbuf.client")) {
650 if (global.tune.client_sndbuf != 0) {
651 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT;
653 goto out;
654 }
655 if (*(args[1]) == 0) {
656 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT | ERR_FATAL;
658 goto out;
659 }
660 global.tune.client_sndbuf = atol(args[1]);
661 }
662 else if (!strcmp(args[0], "tune.sndbuf.server")) {
663 if (global.tune.server_sndbuf != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT;
666 goto out;
667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673 global.tune.server_sndbuf = atol(args[1]);
674 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200675 else if (!strcmp(args[0], "tune.pipesize")) {
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.tune.pipesize = atol(args[1]);
682 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100683 else if (!strcmp(args[0], "tune.http.cookielen")) {
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689 global.tune.cookie_len = atol(args[1]) + 1;
690 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200691 else if (!strcmp(args[0], "tune.http.maxhdr")) {
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 global.tune.max_http_hdr = atol(args[1]);
698 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100699 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
700#ifdef USE_ZLIB
701 if (*args[1]) {
702 global.tune.zlibmemlevel = atoi(args[1]);
703 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
704 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
705 file, linenum, args[0]);
706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
708 }
709 } else {
710 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715#else
716 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719#endif
720 }
721 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
722#ifdef USE_ZLIB
723 if (*args[1]) {
724 global.tune.zlibwindowsize = atoi(args[1]);
725 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
726 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
727 file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 } else {
732 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
733 file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737#else
738 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741#endif
742 }
William Lallemandf3747832012-11-09 12:33:10 +0100743 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
744 if (*args[1]) {
745 global.tune.comp_maxlevel = atoi(args[1]);
746 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
747 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
748 file, linenum, args[0]);
749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
751 }
752 } else {
753 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
754 file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 else if (!strcmp(args[0], "uid")) {
760 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200761 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200762 err_code |= ERR_ALERT;
763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770 global.uid = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "gid")) {
773 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200774 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT;
776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
783 global.gid = atol(args[1]);
784 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 /* user/group name handling */
786 else if (!strcmp(args[0], "user")) {
787 struct passwd *ha_user;
788 if (global.uid != 0) {
789 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200792 }
793 errno = 0;
794 ha_user = getpwnam(args[1]);
795 if (ha_user != NULL) {
796 global.uid = (int)ha_user->pw_uid;
797 }
798 else {
799 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200801 }
802 }
803 else if (!strcmp(args[0], "group")) {
804 struct group *ha_group;
805 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200806 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT;
808 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200809 }
810 errno = 0;
811 ha_group = getgrnam(args[1]);
812 if (ha_group != NULL) {
813 global.gid = (int)ha_group->gr_gid;
814 }
815 else {
816 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200818 }
819 }
820 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 global.nbproc = atol(args[1]);
828 }
829 else if (!strcmp(args[0], "maxconn")) {
830 if (global.maxconn != 0) {
831 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT;
833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840 global.maxconn = atol(args[1]);
841#ifdef SYSTEM_MAXCONN
842 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
843 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
844 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847#endif /* SYSTEM_MAXCONN */
848 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200849 else if (!strcmp(args[0], "maxsslconn")) {
850#ifdef USE_OPENSSL
851 if (*(args[1]) == 0) {
852 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
853 err_code |= ERR_ALERT | ERR_FATAL;
854 goto out;
855 }
856 global.maxsslconn = atol(args[1]);
857#else
Emeric Brun0914df82012-10-02 18:45:42 +0200858 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200861#endif
862 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200863 else if (!strcmp(args[0], "maxconnrate")) {
864 if (global.cps_lim != 0) {
865 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT;
867 goto out;
868 }
869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.cps_lim = atol(args[1]);
875 }
William Lallemandd85f9172012-11-09 17:05:39 +0100876 else if (!strcmp(args[0], "maxcomprate")) {
877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 global.comp_rate_lim = atoi(args[1]) * 1024;
883 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100884 else if (!strcmp(args[0], "maxpipes")) {
885 if (global.maxpipes != 0) {
886 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_ALERT;
888 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100889 }
890 if (*(args[1]) == 0) {
891 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100894 }
895 global.maxpipes = atol(args[1]);
896 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 else if (!strcmp(args[0], "maxzlibmem")) {
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
William Lallemande3a7d992012-11-20 11:25:20 +0100903 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100904 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100905 else if (!strcmp(args[0], "maxcompcpuusage")) {
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100912 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100913 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917}
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 else if (!strcmp(args[0], "ulimit-n")) {
920 if (global.rlimit_nofile != 0) {
921 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
925 if (*(args[1]) == 0) {
926 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930 global.rlimit_nofile = atol(args[1]);
931 }
932 else if (!strcmp(args[0], "chroot")) {
933 if (global.chroot != NULL) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 global.chroot = strdup(args[1]);
944 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200945 else if (!strcmp(args[0], "description")) {
946 int i, len=0;
947 char *d;
948
949 if (!*args[1]) {
950 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
951 file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 for(i=1; *args[i]; i++)
957 len += strlen(args[i])+1;
958
959 if (global.desc)
960 free(global.desc);
961
962 global.desc = d = (char *)calloc(1, len);
963
964 d += sprintf(d, "%s", args[1]);
965 for(i=2; *args[i]; i++)
966 d += sprintf(d, " %s", args[i]);
967 }
968 else if (!strcmp(args[0], "node")) {
969 int i;
970 char c;
971
972 for (i=0; args[1][i]; i++) {
973 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100974 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
975 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200976 break;
977 }
978
979 if (!i || args[1][i]) {
980 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
981 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
982 file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
986
987 if (global.node)
988 free(global.node);
989
990 global.node = strdup(args[1]);
991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "pidfile")) {
993 if (global.pidfile != NULL) {
994 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 }
1003 global.pidfile = strdup(args[1]);
1004 }
Emeric Bruned760922010-10-22 17:59:25 +02001005 else if (!strcmp(args[0], "unix-bind")) {
1006 int cur_arg = 1;
1007 while (*(args[cur_arg])) {
1008 if (!strcmp(args[cur_arg], "prefix")) {
1009 if (global.unix_bind.prefix != NULL) {
1010 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT;
1012 cur_arg += 2;
1013 continue;
1014 }
1015
1016 if (*(args[cur_arg+1]) == 0) {
1017 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020 }
1021 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "mode")) {
1027
1028 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "uid")) {
1034
1035 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "gid")) {
1041
1042 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1043 cur_arg += 2;
1044 continue;
1045 }
1046
1047 if (!strcmp(args[cur_arg], "user")) {
1048 struct passwd *user;
1049
1050 user = getpwnam(args[cur_arg + 1]);
1051 if (!user) {
1052 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1053 file, linenum, args[0], args[cur_arg + 1 ]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057
1058 global.unix_bind.ux.uid = user->pw_uid;
1059 cur_arg += 2;
1060 continue;
1061 }
1062
1063 if (!strcmp(args[cur_arg], "group")) {
1064 struct group *group;
1065
1066 group = getgrnam(args[cur_arg + 1]);
1067 if (!group) {
1068 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1069 file, linenum, args[0], args[cur_arg + 1 ]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073
1074 global.unix_bind.ux.gid = group->gr_gid;
1075 cur_arg += 2;
1076 continue;
1077 }
1078
Willy Tarreaub48f9582011-09-05 01:17:06 +02001079 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001080 file, linenum, args[0]);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084 }
William Lallemand0f99e342011-10-12 17:50:54 +02001085 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1086 /* delete previous herited or defined syslog servers */
1087 struct logsrv *back;
1088 struct logsrv *tmp;
1089
1090 if (*(args[1]) != 0) {
1091 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095
1096 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1097 LIST_DEL(&tmp->list);
1098 free(tmp);
1099 }
1100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001102 struct sockaddr_storage *sk;
1103 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001104 struct logsrv *logsrv;
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 if (*(args[1]) == 0 || *(args[2]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
William Lallemand0f99e342011-10-12 17:50:54 +02001111
1112 logsrv = calloc(1, sizeof(struct logsrv));
1113
1114 logsrv->facility = get_log_facility(args[2]);
1115 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120
William Lallemand0f99e342011-10-12 17:50:54 +02001121 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001123 logsrv->level = get_log_level(args[3]);
1124 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001127 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 }
1130
William Lallemand0f99e342011-10-12 17:50:54 +02001131 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001132 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001133 logsrv->minlvl = get_log_level(args[4]);
1134 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001135 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001137 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001138 }
1139 }
1140
Willy Tarreau902636f2013-03-10 19:44:48 +01001141 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001142 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001143 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001144 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001145 free(logsrv);
1146 goto out;
1147 }
1148 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001149
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001150 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001151 if (port1 != port2) {
1152 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1153 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001154 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001155 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001156 goto out;
1157 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001158
William Lallemand0f99e342011-10-12 17:50:54 +02001159 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001160 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001161 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163
William Lallemand0f99e342011-10-12 17:50:54 +02001164 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001165 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001166 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1167 char *name;
1168 int len;
1169
1170 if (global.log_send_hostname != NULL) {
1171 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT;
1173 goto out;
1174 }
1175
1176 if (*(args[1]))
1177 name = args[1];
1178 else
1179 name = hostname;
1180
1181 len = strlen(name);
1182
1183 /* We'll add a space after the name to respect the log format */
1184 free(global.log_send_hostname);
1185 global.log_send_hostname = malloc(len + 2);
1186 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1187 }
Kevinm48936af2010-12-22 16:08:21 +00001188 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
1193 }
1194 free(global.log_tag);
1195 global.log_tag = strdup(args[1]);
1196 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001197 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1198 if (global.spread_checks != 0) {
1199 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001207 }
1208 global.spread_checks = atol(args[1]);
1209 if (global.spread_checks < 0 || global.spread_checks > 50) {
1210 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001211 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001214 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1215#ifdef USE_CPU_AFFINITY
1216 int cur_arg, i;
1217 unsigned int proc = 0;
1218 unsigned long cpus = 0;
1219
1220 if (strcmp(args[1], "all") == 0)
1221 proc = 0xFFFFFFFF;
1222 else if (strcmp(args[1], "odd") == 0)
1223 proc = 0x55555555;
1224 else if (strcmp(args[1], "even") == 0)
1225 proc = 0xAAAAAAAA;
1226 else {
1227 proc = atoi(args[1]);
1228 if (proc >= 1 && proc <= 32)
1229 proc = 1 << (proc - 1);
1230 }
1231
1232 if (!proc || !*args[2]) {
1233 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1234 file, linenum, args[0]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 cur_arg = 2;
1240 while (*args[cur_arg]) {
1241 unsigned int low, high;
1242
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001243 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001244 char *dash = strchr(args[cur_arg], '-');
1245
1246 low = high = str2uic(args[cur_arg]);
1247 if (dash)
1248 high = str2uic(dash + 1);
1249
1250 if (high < low) {
1251 unsigned int swap = low;
1252 low = high;
1253 high = swap;
1254 }
1255
1256 if (low < 0 || high >= sizeof(long) * 8) {
1257 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1258 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 while (low <= high)
1264 cpus |= 1UL << low++;
1265 }
1266 else {
1267 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1268 file, linenum, args[0], args[cur_arg]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 cur_arg++;
1273 }
1274 for (i = 0; i < 32; i++)
1275 if (proc & (1 << i))
1276 global.cpu_map[i] = cpus;
1277#else
1278 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281#endif
1282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001284 struct cfg_kw_list *kwl;
1285 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001286 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001287
1288 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1289 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1290 if (kwl->kw[index].section != CFG_GLOBAL)
1291 continue;
1292 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001293 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001294 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001295 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001297 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001298 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001299 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_WARN;
1301 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001302 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001304 }
1305 }
1306 }
1307
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001311
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001313 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315}
1316
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001317void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001319 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 defproxy.mode = PR_MODE_TCP;
1321 defproxy.state = PR_STNEW;
1322 defproxy.maxconn = cfg_maxpconn;
1323 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001324
1325 defproxy.defsrv.inter = DEF_CHKINTR;
1326 defproxy.defsrv.fastinter = 0;
1327 defproxy.defsrv.downinter = 0;
1328 defproxy.defsrv.rise = DEF_RISETIME;
1329 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001330 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001331 defproxy.defsrv.maxqueue = 0;
1332 defproxy.defsrv.minconn = 0;
1333 defproxy.defsrv.maxconn = 0;
1334 defproxy.defsrv.slowstart = 0;
1335 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1336 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1337 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338}
1339
Willy Tarreauade5ec42010-01-28 19:33:49 +01001340
1341static int create_cond_regex_rule(const char *file, int line,
1342 struct proxy *px, int dir, int action, int flags,
1343 const char *cmd, const char *reg, const char *repl,
1344 const char **cond_start)
1345{
1346 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001347 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001348 const char *err;
1349 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001350 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001351
1352 if (px == &defproxy) {
1353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto err;
1356 }
1357
1358 if (*reg == 0) {
1359 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1365 err_code |= ERR_WARN;
1366
Willy Tarreau5321c422010-01-28 20:35:13 +01001367 if (cond_start &&
1368 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001369 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1370 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1371 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001372 err_code |= ERR_ALERT | ERR_FATAL;
1373 goto err;
1374 }
1375 }
1376 else if (cond_start && **cond_start) {
1377 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1378 file, line, cmd, *cond_start);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto err;
1381 }
1382
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001383 err_code |= warnif_cond_conflicts(cond,
1384 (dir == SMP_OPT_DIR_REQ) ?
1385 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1386 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1387 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001388
Willy Tarreauade5ec42010-01-28 19:33:49 +01001389 preg = calloc(1, sizeof(regex_t));
1390 if (!preg) {
1391 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1392 err_code = ERR_ALERT | ERR_FATAL;
1393 goto err;
1394 }
1395
1396 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1397 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1398 err_code = ERR_ALERT | ERR_FATAL;
1399 goto err;
1400 }
1401
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001402 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001403 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001404 if (repl && err) {
1405 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1406 file, line, cmd, *err);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 goto err;
1409 }
1410
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001411 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001412 err_code |= ERR_WARN;
1413
Willy Tarreauf4068b62012-05-08 17:37:49 +02001414 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001415 return err_code;
1416 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001417 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001418 free(preg);
1419 return err_code;
1420}
1421
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001424 * Returns the error code, 0 if OK, or any combination of :
1425 * - ERR_ABORT: must abort ASAP
1426 * - ERR_FATAL: we can continue parsing but not start the service
1427 * - ERR_WARN: a warning has been emitted
1428 * - ERR_ALERT: an alert has been emitted
1429 * Only the two first ones can stop processing, the two others are just
1430 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001432int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1433{
1434 static struct peers *curpeers = NULL;
1435 struct peer *newpeer = NULL;
1436 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001437 struct bind_conf *bind_conf;
1438 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001439 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001440 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001441
1442 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001443 if (!*args[1]) {
1444 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001448
1449 err = invalid_char(args[1]);
1450 if (err) {
1451 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1452 file, linenum, *err, args[0], args[1]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001454 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001455 }
1456
1457 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1458 /*
1459 * If there are two proxies with the same name only following
1460 * combinations are allowed:
1461 */
1462 if (strcmp(curpeers->id, args[1]) == 0) {
1463 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1464 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1465 err_code |= ERR_WARN;
1466 }
1467 }
1468
1469 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1471 err_code |= ERR_ALERT | ERR_ABORT;
1472 goto out;
1473 }
1474
1475 curpeers->next = peers;
1476 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001477 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001478 curpeers->conf.line = linenum;
1479 curpeers->last_change = now.tv_sec;
1480 curpeers->id = strdup(args[1]);
1481 }
1482 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001483 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001484 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001485 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001486
1487 if (!*args[2]) {
1488 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1489 file, linenum, args[0]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 err = invalid_char(args[1]);
1495 if (err) {
1496 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1497 file, linenum, *err, args[1]);
1498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1503 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1504 err_code |= ERR_ALERT | ERR_ABORT;
1505 goto out;
1506 }
1507
1508 /* the peers are linked backwards first */
1509 curpeers->count++;
1510 newpeer->next = curpeers->remote;
1511 curpeers->remote = newpeer;
1512 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001513 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001514 newpeer->conf.line = linenum;
1515
1516 newpeer->last_change = now.tv_sec;
1517 newpeer->id = strdup(args[1]);
1518
Willy Tarreau902636f2013-03-10 19:44:48 +01001519 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001520 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001521 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001524 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001525
1526 proto = protocol_by_family(sk->ss_family);
1527 if (!proto || !proto->connect) {
1528 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1529 file, linenum, args[0], args[1]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001533
1534 if (port1 != port2) {
1535 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1536 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
1540
Willy Tarreau2aa38802013-02-20 19:20:59 +01001541 if (!port1) {
1542 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1543 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001547
Emeric Brun32da3c42010-09-23 18:39:19 +02001548 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001549 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001550 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001551 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001552
Emeric Brun32da3c42010-09-23 18:39:19 +02001553 if (strcmp(newpeer->id, localpeer) == 0) {
1554 /* Current is local peer, it define a frontend */
1555 newpeer->local = 1;
1556
1557 if (!curpeers->peers_fe) {
1558 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1559 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1560 err_code |= ERR_ALERT | ERR_ABORT;
1561 goto out;
1562 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001563
Willy Tarreau237250c2011-07-29 01:49:03 +02001564 init_new_proxy(curpeers->peers_fe);
1565 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001566
1567 curpeers->peers_fe->last_change = now.tv_sec;
1568 curpeers->peers_fe->id = strdup(args[1]);
1569 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001570 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001571 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1572 curpeers->peers_fe->timeout.connect = 5000;
1573 curpeers->peers_fe->accept = peer_accept;
1574 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001575 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1576 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001577
1578 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1579
Willy Tarreau902636f2013-03-10 19:44:48 +01001580 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1581 if (errmsg && *errmsg) {
1582 indent_msg(&errmsg, 2);
1583 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001584 }
1585 else
1586 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1587 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001588 err_code |= ERR_FATAL;
1589 goto out;
1590 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001591
1592 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1593 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1594 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1595 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1596 l->accept = session_accept;
1597 l->handler = process_session;
1598 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1599 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1600 global.maxsock += l->maxconn;
1601 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001602 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001603 else {
1604 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1605 file, linenum, args[0], args[1],
1606 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1607 err_code |= ERR_FATAL;
1608 goto out;
1609 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001610 }
1611 } /* neither "peer" nor "peers" */
1612 else if (*args[0] != 0) {
1613 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1614 err_code |= ERR_ALERT | ERR_FATAL;
1615 goto out;
1616 }
1617
1618out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001619 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001620 return err_code;
1621}
1622
1623
Willy Tarreau3842f002009-06-14 11:39:52 +02001624int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625{
1626 static struct proxy *curproxy = NULL;
1627 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001628 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001629 int rc;
1630 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001631 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001632 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001633 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001634 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001635 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636
Willy Tarreau977b8e42006-12-29 14:19:17 +01001637 if (!strcmp(args[0], "listen"))
1638 rc = PR_CAP_LISTEN;
1639 else if (!strcmp(args[0], "frontend"))
1640 rc = PR_CAP_FE | PR_CAP_RS;
1641 else if (!strcmp(args[0], "backend"))
1642 rc = PR_CAP_BE | PR_CAP_RS;
1643 else if (!strcmp(args[0], "ruleset"))
1644 rc = PR_CAP_RS;
1645 else
1646 rc = PR_CAP_NONE;
1647
1648 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 if (!*args[1]) {
1650 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1651 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_ABORT;
1654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001656
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001657 err = invalid_char(args[1]);
1658 if (err) {
1659 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1660 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001661 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001662 }
1663
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001664 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1665 /*
1666 * If there are two proxies with the same name only following
1667 * combinations are allowed:
1668 *
1669 * listen backend frontend ruleset
1670 * listen - - - -
1671 * backend - - OK -
1672 * frontend - OK - -
1673 * ruleset - - - -
1674 */
1675
1676 if (!strcmp(curproxy->id, args[1]) &&
1677 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1678 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001679 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1680 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1681 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001682 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001683 }
1684 }
1685
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1687 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_ABORT;
1689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001691
Willy Tarreau97cb7802010-01-03 20:23:58 +01001692 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693 curproxy->next = proxy;
1694 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001695 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1696 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001697 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001699 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700
1701 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001703 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001704
Willy Tarreau4348fad2012-09-20 16:48:07 +02001705 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1706
Willy Tarreau902636f2013-03-10 19:44:48 +01001707 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1708 if (errmsg && *errmsg) {
1709 indent_msg(&errmsg, 2);
1710 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001711 }
1712 else
1713 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1714 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001715 err_code |= ERR_FATAL;
1716 goto out;
1717 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001718
Willy Tarreau4348fad2012-09-20 16:48:07 +02001719 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001720 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 }
1723
1724 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001725 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001726 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001727
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001730 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001731 curproxy->no_options = defproxy.no_options;
1732 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001733 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001734 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001735 curproxy->except_net = defproxy.except_net;
1736 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001737 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001738 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001740 if (defproxy.fwdfor_hdr_len) {
1741 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1742 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1743 }
1744
Willy Tarreaub86db342009-11-30 11:50:16 +01001745 if (defproxy.orgto_hdr_len) {
1746 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1747 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1748 }
1749
Mark Lamourinec2247f02012-01-04 13:02:01 -05001750 if (defproxy.server_id_hdr_len) {
1751 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1752 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1753 }
1754
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 if (curproxy->cap & PR_CAP_FE) {
1756 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001757 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001758 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001759
1760 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001761 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1762 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763
1764 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766
Willy Tarreau977b8e42006-12-29 14:19:17 +01001767 if (curproxy->cap & PR_CAP_BE) {
1768 curproxy->fullconn = defproxy.fullconn;
1769 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001771 if (defproxy.check_req) {
1772 curproxy->check_req = calloc(1, defproxy.check_len);
1773 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1774 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001775 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001777 if (defproxy.expect_str) {
1778 curproxy->expect_str = strdup(defproxy.expect_str);
1779 if (defproxy.expect_regex) {
1780 /* note: this regex is known to be valid */
1781 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1782 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1783 }
1784 }
1785
Willy Tarreau67402132012-05-31 20:40:20 +02001786 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 if (defproxy.cookie_name)
1788 curproxy->cookie_name = strdup(defproxy.cookie_name);
1789 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001790 if (defproxy.cookie_domain)
1791 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001792
Willy Tarreau31936852010-10-06 16:59:56 +02001793 if (defproxy.cookie_maxidle)
1794 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1795
1796 if (defproxy.cookie_maxlife)
1797 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1798
Emeric Brun647caf12009-06-30 17:57:00 +02001799 if (defproxy.rdp_cookie_name)
1800 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1801 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1802
Willy Tarreau01732802007-11-01 22:48:15 +01001803 if (defproxy.url_param_name)
1804 curproxy->url_param_name = strdup(defproxy.url_param_name);
1805 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001806
Benoitaffb4812009-03-25 13:02:10 +01001807 if (defproxy.hh_name)
1808 curproxy->hh_name = strdup(defproxy.hh_name);
1809 curproxy->hh_len = defproxy.hh_len;
1810 curproxy->hh_match_domain = defproxy.hh_match_domain;
1811
Willy Tarreauef9a3602012-12-08 22:29:20 +01001812 if (defproxy.conn_src.iface_name)
1813 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1814 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1815 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001818 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001819 if (defproxy.capture_name)
1820 curproxy->capture_name = strdup(defproxy.capture_name);
1821 curproxy->capture_namelen = defproxy.capture_namelen;
1822 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001823 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001824
Willy Tarreau977b8e42006-12-29 14:19:17 +01001825 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001826 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001827 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001828 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001829 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001830 curproxy->uri_auth = defproxy.uri_auth;
1831 curproxy->mon_net = defproxy.mon_net;
1832 curproxy->mon_mask = defproxy.mon_mask;
1833 if (defproxy.monitor_uri)
1834 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1835 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001836 if (defproxy.defbe.name)
1837 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001838
1839 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001840 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1841 if (curproxy->conf.logformat_string &&
1842 curproxy->conf.logformat_string != default_http_log_format &&
1843 curproxy->conf.logformat_string != default_tcp_log_format &&
1844 curproxy->conf.logformat_string != clf_http_log_format)
1845 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1846
1847 if (defproxy.conf.lfs_file) {
1848 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1849 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1850 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001851 }
1852
1853 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001854 curproxy->timeout.connect = defproxy.timeout.connect;
1855 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001856 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001857 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001858 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001859 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001860 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001861 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001862 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001863 }
1864
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001866
1867 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001868 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001869 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001870 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001871 LIST_INIT(&node->list);
1872 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1873 }
1874
Willy Tarreau62a61232013-04-12 18:13:46 +02001875 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1876 if (curproxy->conf.uniqueid_format_string)
1877 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1878
1879 if (defproxy.conf.uif_file) {
1880 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1881 curproxy->conf.uif_line = defproxy.conf.uif_line;
1882 }
William Lallemanda73203e2012-03-12 12:48:57 +01001883
1884 /* copy default header unique id */
1885 if (defproxy.header_unique_id)
1886 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1887
William Lallemand82fe75c2012-10-23 10:25:10 +02001888 /* default compression options */
1889 if (defproxy.comp != NULL) {
1890 curproxy->comp = calloc(1, sizeof(struct comp));
1891 curproxy->comp->algos = defproxy.comp->algos;
1892 curproxy->comp->types = defproxy.comp->types;
1893 }
1894
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001896 curproxy->conf.used_listener_id = EB_ROOT;
1897 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001898
Willy Tarreau93893792009-07-23 13:19:11 +02001899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 }
1901 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1902 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001903 /* FIXME-20070101: we should do this too at the end of the
1904 * config parsing to free all default values.
1905 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001906 free(defproxy.check_req);
1907 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001908 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001909 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001910 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001911 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001912 free(defproxy.capture_name);
1913 free(defproxy.monitor_uri);
1914 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001915 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001916 free(defproxy.fwdfor_hdr_name);
1917 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001918 free(defproxy.orgto_hdr_name);
1919 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001920 free(defproxy.server_id_hdr_name);
1921 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001922 free(defproxy.expect_str);
1923 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001924
Willy Tarreau62a61232013-04-12 18:13:46 +02001925 if (defproxy.conf.logformat_string != default_http_log_format &&
1926 defproxy.conf.logformat_string != default_tcp_log_format &&
1927 defproxy.conf.logformat_string != clf_http_log_format)
1928 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001929
Willy Tarreau62a61232013-04-12 18:13:46 +02001930 free(defproxy.conf.uniqueid_format_string);
1931 free(defproxy.conf.lfs_file);
1932 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001933
Willy Tarreaua534fea2008-08-03 12:19:50 +02001934 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001935 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001936
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 /* we cannot free uri_auth because it might already be used */
1938 init_default_instance();
1939 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001940 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1941 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001942 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 }
1945 else if (curproxy == NULL) {
1946 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001950
1951 /* update the current file and line being parsed */
1952 curproxy->conf.args.file = curproxy->conf.file;
1953 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001954
1955 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001957 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001958 int cur_arg;
1959
Willy Tarreaubaaee002006-06-26 02:48:02 +02001960 if (curproxy == &defproxy) {
1961 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001962 err_code |= ERR_ALERT | ERR_FATAL;
1963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001964 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001965 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001966 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967
Willy Tarreau24709282013-03-10 21:32:12 +01001968 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001969 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001971 err_code |= ERR_ALERT | ERR_FATAL;
1972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001974
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001975 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001976
1977 /* use default settings for unix sockets */
1978 bind_conf->ux.uid = global.unix_bind.ux.uid;
1979 bind_conf->ux.gid = global.unix_bind.ux.gid;
1980 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001981
1982 /* NOTE: the following line might create several listeners if there
1983 * are comma-separated IPs or port ranges. So all further processing
1984 * will have to be applied to all listeners created after last_listen.
1985 */
Willy Tarreau902636f2013-03-10 19:44:48 +01001986 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
1987 if (errmsg && *errmsg) {
1988 indent_msg(&errmsg, 2);
1989 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001990 }
1991 else
1992 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1993 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001994 err_code |= ERR_ALERT | ERR_FATAL;
1995 goto out;
1996 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001997
Willy Tarreau4348fad2012-09-20 16:48:07 +02001998 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1999 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002000 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002001 }
2002
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002003 cur_arg = 2;
2004 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002005 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002006 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002007 char *err;
2008
Willy Tarreau26982662012-09-12 23:17:10 +02002009 kw = bind_find_kw(args[cur_arg]);
2010 if (kw) {
2011 char *err = NULL;
2012 int code;
2013
2014 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002015 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2016 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002017 cur_arg += 1 + kw->skip ;
2018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
2020 }
2021
Willy Tarreau4348fad2012-09-20 16:48:07 +02002022 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002023 err_code |= code;
2024
2025 if (code) {
2026 if (err && *err) {
2027 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002028 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002029 }
2030 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002031 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2032 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002033 if (code & ERR_FATAL) {
2034 free(err);
2035 cur_arg += 1 + kw->skip;
2036 goto out;
2037 }
2038 }
2039 free(err);
2040 cur_arg += 1 + kw->skip;
2041 continue;
2042 }
2043
Willy Tarreau8638f482012-09-18 18:01:17 +02002044 err = NULL;
2045 if (!bind_dumped) {
2046 bind_dump_kws(&err);
2047 indent_msg(&err, 4);
2048 bind_dumped = 1;
2049 }
2050
2051 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2052 file, linenum, args[0], args[1], args[cur_arg],
2053 err ? " Registered keywords :" : "", err ? err : "");
2054 free(err);
2055
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002058 }
Willy Tarreau93893792009-07-23 13:19:11 +02002059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 }
2061 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2062 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2063 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002069 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002070
Willy Tarreaubaaee002006-06-26 02:48:02 +02002071 /* flush useless bits */
2072 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002075 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002076 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002077 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002078
Willy Tarreau1c47f852006-07-09 08:22:27 +02002079 if (!*args[1]) {
2080 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2081 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002084 }
2085
Willy Tarreaua534fea2008-08-03 12:19:50 +02002086 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002087 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002088 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002089 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002090 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2091
Willy Tarreau93893792009-07-23 13:19:11 +02002092 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2095 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2096 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2097 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2098 else {
2099 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 }
2103 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002104 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002105 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002106
2107 if (curproxy == &defproxy) {
2108 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2109 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
2111 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002112 }
2113
2114 if (!*args[1]) {
2115 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2116 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002119 }
2120
2121 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002122 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002123
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002124 if (curproxy->uuid <= 0) {
2125 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002126 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002127 err_code |= ERR_ALERT | ERR_FATAL;
2128 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002129 }
2130
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002131 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2132 if (node) {
2133 struct proxy *target = container_of(node, struct proxy, conf.id);
2134 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2135 file, linenum, proxy_type_str(curproxy), curproxy->id,
2136 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2137 err_code |= ERR_ALERT | ERR_FATAL;
2138 goto out;
2139 }
2140 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002141 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002142 else if (!strcmp(args[0], "description")) {
2143 int i, len=0;
2144 char *d;
2145
Cyril Bonté99ed3272010-01-24 23:29:44 +01002146 if (curproxy == &defproxy) {
2147 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2148 file, linenum, args[0]);
2149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
2151 }
2152
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002153 if (!*args[1]) {
2154 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2155 file, linenum, args[0]);
2156 return -1;
2157 }
2158
2159 for(i=1; *args[i]; i++)
2160 len += strlen(args[i])+1;
2161
2162 d = (char *)calloc(1, len);
2163 curproxy->desc = d;
2164
2165 d += sprintf(d, "%s", args[1]);
2166 for(i=2; *args[i]; i++)
2167 d += sprintf(d, " %s", args[i]);
2168
2169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2171 curproxy->state = PR_STSTOPPED;
2172 }
2173 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2174 curproxy->state = PR_STNEW;
2175 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002176 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2177 int cur_arg = 1;
2178 unsigned int set = 0;
2179
2180 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002181 unsigned int low, high;
2182
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002183 if (strcmp(args[cur_arg], "all") == 0) {
2184 set = 0;
2185 break;
2186 }
2187 else if (strcmp(args[cur_arg], "odd") == 0) {
2188 set |= 0x55555555;
2189 }
2190 else if (strcmp(args[cur_arg], "even") == 0) {
2191 set |= 0xAAAAAAAA;
2192 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002193 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002194 char *dash = strchr(args[cur_arg], '-');
2195
2196 low = high = str2uic(args[cur_arg]);
2197 if (dash)
2198 high = str2uic(dash + 1);
2199
2200 if (high < low) {
2201 unsigned int swap = low;
2202 low = high;
2203 high = swap;
2204 }
2205
2206 if (low < 1 || high > 32) {
2207 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002208 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002211 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002212
2213 if (high > global.nbproc) {
2214 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2215 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002217 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002218 while (low <= high)
2219 set |= 1 << (low++ - 1);
2220 }
2221 else {
2222 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2223 file, linenum, args[0]);
2224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002226 }
2227 cur_arg++;
2228 }
2229 curproxy->bind_proc = set;
2230 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002231 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002232 if (curproxy == &defproxy) {
2233 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002236 }
2237
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002238 err = invalid_char(args[1]);
2239 if (err) {
2240 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2241 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002243 }
2244
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002245 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002246 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2247 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002250 }
2251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2253 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254
Willy Tarreau977b8e42006-12-29 14:19:17 +01002255 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002256 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002257
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 if (*(args[1]) == 0) {
2259 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2260 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002264
Willy Tarreau67402132012-05-31 20:40:20 +02002265 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002266 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002267 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002268 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 curproxy->cookie_name = strdup(args[1]);
2270 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002271
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 cur_arg = 2;
2273 while (*(args[cur_arg])) {
2274 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002275 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 }
2277 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002278 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }
2280 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002281 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 }
2283 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002284 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 }
2286 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002287 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002289 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002290 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002293 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002295 else if (!strcmp(args[cur_arg], "httponly")) {
2296 curproxy->ck_opts |= PR_CK_HTTPONLY;
2297 }
2298 else if (!strcmp(args[cur_arg], "secure")) {
2299 curproxy->ck_opts |= PR_CK_SECURE;
2300 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002301 else if (!strcmp(args[cur_arg], "domain")) {
2302 if (!*args[cur_arg + 1]) {
2303 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2304 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002307 }
2308
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002309 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002310 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002311 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2312 " dots nor does not start with a dot."
2313 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002314 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002315 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002316 }
2317
2318 err = invalid_domainchar(args[cur_arg + 1]);
2319 if (err) {
2320 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2321 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002324 }
2325
Willy Tarreau68a897b2009-12-03 23:28:34 +01002326 if (!curproxy->cookie_domain) {
2327 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2328 } else {
2329 /* one domain was already specified, add another one by
2330 * building the string which will be returned along with
2331 * the cookie.
2332 */
2333 char *new_ptr;
2334 int new_len = strlen(curproxy->cookie_domain) +
2335 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2336 new_ptr = malloc(new_len);
2337 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2338 free(curproxy->cookie_domain);
2339 curproxy->cookie_domain = new_ptr;
2340 }
Willy Tarreau31936852010-10-06 16:59:56 +02002341 cur_arg++;
2342 }
2343 else if (!strcmp(args[cur_arg], "maxidle")) {
2344 unsigned int maxidle;
2345 const char *res;
2346
2347 if (!*args[cur_arg + 1]) {
2348 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2349 file, linenum, args[cur_arg]);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
2353
2354 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2355 if (res) {
2356 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2357 file, linenum, *res, args[cur_arg]);
2358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
2360 }
2361 curproxy->cookie_maxidle = maxidle;
2362 cur_arg++;
2363 }
2364 else if (!strcmp(args[cur_arg], "maxlife")) {
2365 unsigned int maxlife;
2366 const char *res;
2367
2368 if (!*args[cur_arg + 1]) {
2369 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2370 file, linenum, args[cur_arg]);
2371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
2373 }
2374
2375 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2376 if (res) {
2377 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2378 file, linenum, *res, args[cur_arg]);
2379 err_code |= ERR_ALERT | ERR_FATAL;
2380 goto out;
2381 }
2382 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002383 cur_arg++;
2384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002386 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 +02002387 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 }
2391 cur_arg++;
2392 }
Willy Tarreau67402132012-05-31 20:40:20 +02002393 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2395 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 }
2398
Willy Tarreau67402132012-05-31 20:40:20 +02002399 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2401 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002402 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002404
Willy Tarreau67402132012-05-31 20:40:20 +02002405 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002406 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2407 file, linenum);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002411 else if (!strcmp(args[0], "persist")) { /* persist */
2412 if (*(args[1]) == 0) {
2413 Alert("parsing [%s:%d] : missing persist method.\n",
2414 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002417 }
2418
2419 if (!strncmp(args[1], "rdp-cookie", 10)) {
2420 curproxy->options2 |= PR_O2_RDPC_PRST;
2421
Emeric Brunb982a3d2010-01-04 15:45:53 +01002422 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002423 const char *beg, *end;
2424
2425 beg = args[1] + 11;
2426 end = strchr(beg, ')');
2427
2428 if (!end || end == beg) {
2429 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2430 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002433 }
2434
2435 free(curproxy->rdp_cookie_name);
2436 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2437 curproxy->rdp_cookie_len = end-beg;
2438 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002439 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002440 free(curproxy->rdp_cookie_name);
2441 curproxy->rdp_cookie_name = strdup("msts");
2442 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2443 }
2444 else { /* syntax */
2445 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2446 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002449 }
2450 }
2451 else {
2452 Alert("parsing [%s:%d] : unknown persist method.\n",
2453 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002456 }
2457 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002459 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002461 if (curproxy == &defproxy) {
2462 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
2465 }
2466
Willy Tarreau977b8e42006-12-29 14:19:17 +01002467 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002469
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002471 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_FATAL;
2474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 }
2476 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002477 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 curproxy->appsession_name = strdup(args[1]);
2479 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2480 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002481 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2482 if (err) {
2483 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2484 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002487 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002488 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002489
Willy Tarreau51041c72007-09-09 21:56:53 +02002490 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2491 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_ABORT;
2493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002495
2496 cur_arg = 6;
2497 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002498 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2499 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002500 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002501 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002502 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002503 } else if (!strcmp(args[cur_arg], "prefix")) {
2504 curproxy->options2 |= PR_O2_AS_PFX;
2505 } else if (!strcmp(args[cur_arg], "mode")) {
2506 if (!*args[cur_arg + 1]) {
2507 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2508 file, linenum, args[0], args[cur_arg]);
2509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
2511 }
2512
2513 cur_arg++;
2514 if (!strcmp(args[cur_arg], "query-string")) {
2515 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2516 curproxy->options2 |= PR_O2_AS_M_QS;
2517 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2518 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2519 curproxy->options2 |= PR_O2_AS_M_PP;
2520 } else {
2521 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002526 cur_arg++;
2527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 } /* Url App Session */
2529 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002530 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002532
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002534 if (curproxy == &defproxy) {
2535 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
2538 }
2539
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 if (*(args[4]) == 0) {
2541 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2542 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002546 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 curproxy->capture_name = strdup(args[2]);
2548 curproxy->capture_namelen = strlen(curproxy->capture_name);
2549 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 curproxy->to_log |= LW_COOKIE;
2551 }
2552 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2553 struct cap_hdr *hdr;
2554
2555 if (curproxy == &defproxy) {
2556 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 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
2560
2561 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2562 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2563 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 }
2567
2568 hdr = calloc(sizeof(struct cap_hdr), 1);
2569 hdr->next = curproxy->req_cap;
2570 hdr->name = strdup(args[3]);
2571 hdr->namelen = strlen(args[3]);
2572 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002573 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 hdr->index = curproxy->nb_req_cap++;
2575 curproxy->req_cap = hdr;
2576 curproxy->to_log |= LW_REQHDR;
2577 }
2578 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2579 struct cap_hdr *hdr;
2580
2581 if (curproxy == &defproxy) {
2582 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 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
2586
2587 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2588 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2589 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 }
2593 hdr = calloc(sizeof(struct cap_hdr), 1);
2594 hdr->next = curproxy->rsp_cap;
2595 hdr->name = strdup(args[3]);
2596 hdr->namelen = strlen(args[3]);
2597 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002598 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 hdr->index = curproxy->nb_rsp_cap++;
2600 curproxy->rsp_cap = hdr;
2601 curproxy->to_log |= LW_RSPHDR;
2602 }
2603 else {
2604 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2605 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002606 err_code |= ERR_ALERT | ERR_FATAL;
2607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 }
2609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002611 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002613
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 if (*(args[1]) == 0) {
2615 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2616 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619 }
2620 curproxy->conn_retries = atol(args[1]);
2621 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002622 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002623 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002624
2625 if (curproxy == &defproxy) {
2626 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
2629 }
2630
Willy Tarreau20b0de52012-12-24 15:45:22 +01002631 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2632 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2633 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2634 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2635 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2636 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 +01002637 file, linenum, args[0]);
2638 err_code |= ERR_WARN;
2639 }
2640
Willy Tarreauff011f22011-01-06 17:51:27 +01002641 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002642
Willy Tarreauff011f22011-01-06 17:51:27 +01002643 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002644 err_code |= ERR_ALERT | ERR_ABORT;
2645 goto out;
2646 }
2647
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002648 err_code |= warnif_cond_conflicts(rule->cond,
2649 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2650 file, linenum);
2651
Willy Tarreauff011f22011-01-06 17:51:27 +01002652 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002653 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002654 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2655 /* set the header name and length into the proxy structure */
2656 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2657 err_code |= ERR_WARN;
2658
2659 if (!*args[1]) {
2660 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2661 file, linenum, args[0]);
2662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
2664 }
2665
2666 /* set the desired header name */
2667 free(curproxy->server_id_hdr_name);
2668 curproxy->server_id_hdr_name = strdup(args[1]);
2669 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2670 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002671 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002672 if (curproxy == &defproxy) {
2673 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002676 }
2677
Willy Tarreauef6494c2010-01-28 17:12:36 +01002678 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002679 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2680 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002683 }
2684
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002685 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2686 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2687 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_ALERT | ERR_FATAL;
2689 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002690 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002691
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002692 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002693 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002694 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002695 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002696 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002697
Cyril Bonté99ed3272010-01-24 23:29:44 +01002698 if (curproxy == &defproxy) {
2699 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
2702 }
2703
Willy Tarreau4baae242012-12-27 12:00:31 +01002704 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2705 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2706 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002707 err_code |= ERR_ALERT | ERR_FATAL;
2708 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002709 }
2710
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002711 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002712 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002713 err_code |= warnif_cond_conflicts(rule->cond,
2714 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2715 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002716 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002717 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002718 struct switching_rule *rule;
2719
Willy Tarreaub099aca2008-10-12 17:26:37 +02002720 if (curproxy == &defproxy) {
2721 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002724 }
2725
Willy Tarreau55ea7572007-06-17 19:56:27 +02002726 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002727 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002728
2729 if (*(args[1]) == 0) {
2730 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002733 }
2734
Willy Tarreauef6494c2010-01-28 17:12:36 +01002735 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002736 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2737 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002740 }
2741
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002742 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2743 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2744 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002747 }
2748
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002749 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002750
Willy Tarreau55ea7572007-06-17 19:56:27 +02002751 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2752 rule->cond = cond;
2753 rule->be.name = strdup(args[1]);
2754 LIST_INIT(&rule->list);
2755 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2756 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002757 else if (strcmp(args[0], "use-server") == 0) {
2758 struct server_rule *rule;
2759
2760 if (curproxy == &defproxy) {
2761 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
2764 }
2765
2766 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2767 err_code |= ERR_WARN;
2768
2769 if (*(args[1]) == 0) {
2770 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
2773 }
2774
2775 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2776 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2777 file, linenum, args[0]);
2778 err_code |= ERR_ALERT | ERR_FATAL;
2779 goto out;
2780 }
2781
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002782 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2783 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2784 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
2787 }
2788
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002789 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002790
2791 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2792 rule->cond = cond;
2793 rule->srv.name = strdup(args[1]);
2794 LIST_INIT(&rule->list);
2795 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2796 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2797 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002798 else if ((!strcmp(args[0], "force-persist")) ||
2799 (!strcmp(args[0], "ignore-persist"))) {
2800 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002801
2802 if (curproxy == &defproxy) {
2803 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
2807
2808 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2809 err_code |= ERR_WARN;
2810
Willy Tarreauef6494c2010-01-28 17:12:36 +01002811 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002812 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2813 file, linenum, args[0]);
2814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
2816 }
2817
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002818 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2819 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2820 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
2823 }
2824
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002825 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2826 * where force-persist is applied.
2827 */
2828 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002829
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002830 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002831 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002832 if (!strcmp(args[0], "force-persist")) {
2833 rule->type = PERSIST_TYPE_FORCE;
2834 } else {
2835 rule->type = PERSIST_TYPE_IGNORE;
2836 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002837 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002838 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002839 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002840 else if (!strcmp(args[0], "stick-table")) {
2841 int myidx = 1;
2842
Emeric Brun32da3c42010-09-23 18:39:19 +02002843 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002844 curproxy->table.type = (unsigned int)-1;
2845 while (*args[myidx]) {
2846 const char *err;
2847
2848 if (strcmp(args[myidx], "size") == 0) {
2849 myidx++;
2850 if (!*(args[myidx])) {
2851 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2852 file, linenum, args[myidx-1]);
2853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
2855 }
2856 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2857 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2858 file, linenum, *err, args[myidx-1]);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002862 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002863 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002864 else if (strcmp(args[myidx], "peers") == 0) {
2865 myidx++;
2866 if (!*(args[myidx])) {
2867 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2868 file, linenum, args[myidx-1]);
2869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872 curproxy->table.peers.name = strdup(args[myidx++]);
2873 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002874 else if (strcmp(args[myidx], "expire") == 0) {
2875 myidx++;
2876 if (!*(args[myidx])) {
2877 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2878 file, linenum, args[myidx-1]);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2883 if (err) {
2884 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2885 file, linenum, *err, args[myidx-1]);
2886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
2888 }
2889 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002890 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002891 }
2892 else if (strcmp(args[myidx], "nopurge") == 0) {
2893 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002894 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002895 }
2896 else if (strcmp(args[myidx], "type") == 0) {
2897 myidx++;
2898 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2899 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2900 file, linenum, args[myidx]);
2901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
2903 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002904 /* myidx already points to next arg */
2905 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002906 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002907 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002908 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002909
2910 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002911 nw = args[myidx];
2912 while (*nw) {
2913 /* the "store" keyword supports a comma-separated list */
2914 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002915 sa = NULL; /* store arg */
2916 while (*nw && *nw != ',') {
2917 if (*nw == '(') {
2918 *nw = 0;
2919 sa = ++nw;
2920 while (*nw != ')') {
2921 if (!*nw) {
2922 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2923 file, linenum, args[0], cw);
2924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
2926 }
2927 nw++;
2928 }
2929 *nw = '\0';
2930 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002931 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002932 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002933 if (*nw)
2934 *nw++ = '\0';
2935 type = stktable_get_data_type(cw);
2936 if (type < 0) {
2937 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2938 file, linenum, args[0], cw);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941 }
Willy Tarreauac782882010-06-20 10:41:54 +02002942
2943 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2944 switch (err) {
2945 case PE_NONE: break;
2946 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002947 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2948 file, linenum, args[0], cw);
2949 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002950 break;
2951
2952 case PE_ARG_MISSING:
2953 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2954 file, linenum, args[0], cw);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957
2958 case PE_ARG_NOT_USED:
2959 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2960 file, linenum, args[0], cw);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963
2964 default:
2965 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2966 file, linenum, args[0], cw);
2967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002969 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002970 }
2971 myidx++;
2972 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002973 else {
2974 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2975 file, linenum, args[myidx]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002978 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002979 }
2980
2981 if (!curproxy->table.size) {
2982 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2983 file, linenum);
2984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
2986 }
2987
2988 if (curproxy->table.type == (unsigned int)-1) {
2989 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2990 file, linenum);
2991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
2993 }
2994 }
2995 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002996 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002997 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002998 int myidx = 0;
2999 const char *name = NULL;
3000 int flags;
3001
3002 if (curproxy == &defproxy) {
3003 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007
3008 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3009 err_code |= ERR_WARN;
3010 goto out;
3011 }
3012
3013 myidx++;
3014 if ((strcmp(args[myidx], "store") == 0) ||
3015 (strcmp(args[myidx], "store-request") == 0)) {
3016 myidx++;
3017 flags = STK_IS_STORE;
3018 }
3019 else if (strcmp(args[myidx], "store-response") == 0) {
3020 myidx++;
3021 flags = STK_IS_STORE | STK_ON_RSP;
3022 }
3023 else if (strcmp(args[myidx], "match") == 0) {
3024 myidx++;
3025 flags = STK_IS_MATCH;
3026 }
3027 else if (strcmp(args[myidx], "on") == 0) {
3028 myidx++;
3029 flags = STK_IS_MATCH | STK_IS_STORE;
3030 }
3031 else {
3032 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
3035 }
3036
3037 if (*(args[myidx]) == 0) {
3038 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
3041 }
3042
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003043 curproxy->conf.args.ctx = ARGC_STK;
3044 expr = sample_parse_expr(args, &myidx, trash.str, trash.size, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003046 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
3049 }
3050
3051 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003052 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3053 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3054 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003055 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003056 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003057 goto out;
3058 }
3059 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003060 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3061 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3062 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003063 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003064 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003065 goto out;
3066 }
3067 }
3068
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003069 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003070 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003071
Emeric Brunb982a3d2010-01-04 15:45:53 +01003072 if (strcmp(args[myidx], "table") == 0) {
3073 myidx++;
3074 name = args[myidx++];
3075 }
3076
Willy Tarreauef6494c2010-01-28 17:12:36 +01003077 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003078 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3079 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3080 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003081 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003082 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003083 goto out;
3084 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003085 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003086 else if (*(args[myidx])) {
3087 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3088 file, linenum, args[0], args[myidx]);
3089 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003090 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003091 goto out;
3092 }
Emeric Brun97679e72010-09-23 17:56:44 +02003093 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003094 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003095 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003096 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003097
Emeric Brunb982a3d2010-01-04 15:45:53 +01003098 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3099 rule->cond = cond;
3100 rule->expr = expr;
3101 rule->flags = flags;
3102 rule->table.name = name ? strdup(name) : NULL;
3103 LIST_INIT(&rule->list);
3104 if (flags & STK_ON_RSP)
3105 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3106 else
3107 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003110 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003111 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003112
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3114 curproxy->uri_auth = NULL; /* we must detach from the default config */
3115
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003116 if (!*args[1]) {
3117 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003118 } else if (!strcmp(args[1], "admin")) {
3119 struct stats_admin_rule *rule;
3120
3121 if (curproxy == &defproxy) {
3122 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
3125 }
3126
3127 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3128 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3129 err_code |= ERR_ALERT | ERR_ABORT;
3130 goto out;
3131 }
3132
3133 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3134 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3135 file, linenum, args[0], args[1]);
3136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
3138 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003139 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3140 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3141 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
3144 }
3145
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003146 err_code |= warnif_cond_conflicts(cond,
3147 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3148 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003149
3150 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3151 rule->cond = cond;
3152 LIST_INIT(&rule->list);
3153 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 } else if (!strcmp(args[1], "uri")) {
3155 if (*(args[2]) == 0) {
3156 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_ALERT | ERR_FATAL;
3158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3160 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003161 err_code |= ERR_ALERT | ERR_ABORT;
3162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 }
3164 } else if (!strcmp(args[1], "realm")) {
3165 if (*(args[2]) == 0) {
3166 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3170 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_ABORT;
3172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003174 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003175 unsigned interval;
3176
3177 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3178 if (err) {
3179 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3180 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003183 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3184 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003185 err_code |= ERR_ALERT | ERR_ABORT;
3186 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003187 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003188 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003189 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003190
3191 if (curproxy == &defproxy) {
3192 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
3196
3197 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3198 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3199 err_code |= ERR_ALERT | ERR_ABORT;
3200 goto out;
3201 }
3202
Willy Tarreauff011f22011-01-06 17:51:27 +01003203 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3204 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003205 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3206 file, linenum, args[0]);
3207 err_code |= ERR_WARN;
3208 }
3209
Willy Tarreauff011f22011-01-06 17:51:27 +01003210 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003211
Willy Tarreauff011f22011-01-06 17:51:27 +01003212 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003213 err_code |= ERR_ALERT | ERR_ABORT;
3214 goto out;
3215 }
3216
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003217 err_code |= warnif_cond_conflicts(rule->cond,
3218 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3219 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003220 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003221
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 } else if (!strcmp(args[1], "auth")) {
3223 if (*(args[2]) == 0) {
3224 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3228 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003229 err_code |= ERR_ALERT | ERR_ABORT;
3230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 }
3232 } else if (!strcmp(args[1], "scope")) {
3233 if (*(args[2]) == 0) {
3234 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3238 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_ABORT;
3240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 }
3242 } else if (!strcmp(args[1], "enable")) {
3243 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3244 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_ABORT;
3246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003248 } else if (!strcmp(args[1], "hide-version")) {
3249 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3250 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_ALERT | ERR_ABORT;
3252 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003253 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003254 } else if (!strcmp(args[1], "show-legends")) {
3255 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3256 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3257 err_code |= ERR_ALERT | ERR_ABORT;
3258 goto out;
3259 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003260 } else if (!strcmp(args[1], "show-node")) {
3261
3262 if (*args[2]) {
3263 int i;
3264 char c;
3265
3266 for (i=0; args[2][i]; i++) {
3267 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003268 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3269 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003270 break;
3271 }
3272
3273 if (!i || args[2][i]) {
3274 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3275 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3276 file, linenum, args[0], args[1]);
3277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
3279 }
3280 }
3281
3282 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3283 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3284 err_code |= ERR_ALERT | ERR_ABORT;
3285 goto out;
3286 }
3287 } else if (!strcmp(args[1], "show-desc")) {
3288 char *desc = NULL;
3289
3290 if (*args[2]) {
3291 int i, len=0;
3292 char *d;
3293
3294 for(i=2; *args[i]; i++)
3295 len += strlen(args[i])+1;
3296
3297 desc = d = (char *)calloc(1, len);
3298
3299 d += sprintf(d, "%s", args[2]);
3300 for(i=3; *args[i]; i++)
3301 d += sprintf(d, " %s", args[i]);
3302 }
3303
3304 if (!*args[2] && !global.desc)
3305 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3306 file, linenum, args[1]);
3307 else {
3308 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3309 free(desc);
3310 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3311 err_code |= ERR_ALERT | ERR_ABORT;
3312 goto out;
3313 }
3314 free(desc);
3315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003317stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003318 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 +01003319 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 }
3323 }
3324 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003325 int optnum;
3326
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003327 if (*(args[1]) == '\0') {
3328 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3329 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003333
3334 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3335 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003336 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3337 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3338 file, linenum, cfg_opts[optnum].name);
3339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
3341 }
Willy Tarreau93893792009-07-23 13:19:11 +02003342 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3343 err_code |= ERR_WARN;
3344 goto out;
3345 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003346
Willy Tarreau3842f002009-06-14 11:39:52 +02003347 curproxy->no_options &= ~cfg_opts[optnum].val;
3348 curproxy->options &= ~cfg_opts[optnum].val;
3349
3350 switch (kwm) {
3351 case KWM_STD:
3352 curproxy->options |= cfg_opts[optnum].val;
3353 break;
3354 case KWM_NO:
3355 curproxy->no_options |= cfg_opts[optnum].val;
3356 break;
3357 case KWM_DEF: /* already cleared */
3358 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003359 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003360
Willy Tarreau93893792009-07-23 13:19:11 +02003361 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003362 }
3363 }
3364
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003365 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3366 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003367 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3368 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3369 file, linenum, cfg_opts2[optnum].name);
3370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
3372 }
Willy Tarreau93893792009-07-23 13:19:11 +02003373 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3374 err_code |= ERR_WARN;
3375 goto out;
3376 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003377
Willy Tarreau3842f002009-06-14 11:39:52 +02003378 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3379 curproxy->options2 &= ~cfg_opts2[optnum].val;
3380
3381 switch (kwm) {
3382 case KWM_STD:
3383 curproxy->options2 |= cfg_opts2[optnum].val;
3384 break;
3385 case KWM_NO:
3386 curproxy->no_options2 |= cfg_opts2[optnum].val;
3387 break;
3388 case KWM_DEF: /* already cleared */
3389 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003390 }
Willy Tarreau93893792009-07-23 13:19:11 +02003391 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003392 }
3393 }
3394
Willy Tarreau3842f002009-06-14 11:39:52 +02003395 if (kwm != KWM_STD) {
3396 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003397 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003400 }
3401
Emeric Brun3a058f32009-06-30 18:26:00 +02003402 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003403 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003405 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003406 if (*(args[2]) != '\0') {
3407 if (!strcmp(args[2], "clf")) {
3408 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003409 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003410 } else {
3411 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_ALERT | ERR_FATAL;
3413 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003414 }
3415 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003416 if (curproxy->conf.logformat_string != default_http_log_format &&
3417 curproxy->conf.logformat_string != default_tcp_log_format &&
3418 curproxy->conf.logformat_string != clf_http_log_format)
3419 free(curproxy->conf.logformat_string);
3420 curproxy->conf.logformat_string = logformat;
3421
3422 free(curproxy->conf.lfs_file);
3423 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3424 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003425 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003426 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003428 if (curproxy->conf.logformat_string != default_http_log_format &&
3429 curproxy->conf.logformat_string != default_tcp_log_format &&
3430 curproxy->conf.logformat_string != clf_http_log_format)
3431 free(curproxy->conf.logformat_string);
3432 curproxy->conf.logformat_string = default_tcp_log_format;
3433
3434 free(curproxy->conf.lfs_file);
3435 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3436 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 else if (!strcmp(args[1], "tcpka")) {
3439 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003440 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003441 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003442
3443 if (curproxy->cap & PR_CAP_FE)
3444 curproxy->options |= PR_O_TCP_CLI_KA;
3445 if (curproxy->cap & PR_CAP_BE)
3446 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 }
3448 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003449 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_WARN;
3451
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003453 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003454 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003455 curproxy->options2 &= ~PR_O2_CHK_ANY;
3456 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003457 if (!*args[2]) { /* no argument */
3458 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3459 curproxy->check_len = strlen(DEF_CHECK_REQ);
3460 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003461 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003462 curproxy->check_req = (char *)malloc(reqlen);
3463 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003464 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003466 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 if (*args[4])
3468 reqlen += strlen(args[4]);
3469 else
3470 reqlen += strlen("HTTP/1.0");
3471
3472 curproxy->check_req = (char *)malloc(reqlen);
3473 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003474 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003475 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003476 }
3477 else if (!strcmp(args[1], "ssl-hello-chk")) {
3478 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003479 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003480 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003481
Willy Tarreaua534fea2008-08-03 12:19:50 +02003482 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003483 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003484 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003485 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 }
Willy Tarreau23677902007-05-08 23:50:35 +02003487 else if (!strcmp(args[1], "smtpchk")) {
3488 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003489 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003490 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003491 curproxy->options2 &= ~PR_O2_CHK_ANY;
3492 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003493
3494 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3495 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3496 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3497 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3498 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3499 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3500 curproxy->check_req = (char *)malloc(reqlen);
3501 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3502 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3503 } else {
3504 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3505 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3506 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3507 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3508 }
3509 }
3510 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003511 else if (!strcmp(args[1], "lb-agent-chk")) {
3512 /* use dynmaic health check */
3513 free(curproxy->check_req);
3514 curproxy->check_req = NULL;
3515 curproxy->options2 &= ~PR_O2_CHK_ANY;
3516 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3517 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003518 else if (!strcmp(args[1], "pgsql-check")) {
3519 /* use PostgreSQL request to check servers' health */
3520 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3521 err_code |= ERR_WARN;
3522
3523 free(curproxy->check_req);
3524 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003525 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003526 curproxy->options2 |= PR_O2_PGSQL_CHK;
3527
3528 if (*(args[2])) {
3529 int cur_arg = 2;
3530
3531 while (*(args[cur_arg])) {
3532 if (strcmp(args[cur_arg], "user") == 0) {
3533 char * packet;
3534 uint32_t packet_len;
3535 uint32_t pv;
3536
3537 /* suboption header - needs additional argument for it */
3538 if (*(args[cur_arg+1]) == 0) {
3539 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3540 file, linenum, args[0], args[1], args[cur_arg]);
3541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
3543 }
3544
3545 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3546 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3547 pv = htonl(0x30000); /* protocol version 3.0 */
3548
3549 packet = (char*) calloc(1, packet_len);
3550
3551 memcpy(packet + 4, &pv, 4);
3552
3553 /* copy "user" */
3554 memcpy(packet + 8, "user", 4);
3555
3556 /* copy username */
3557 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3558
3559 free(curproxy->check_req);
3560 curproxy->check_req = packet;
3561 curproxy->check_len = packet_len;
3562
3563 packet_len = htonl(packet_len);
3564 memcpy(packet, &packet_len, 4);
3565 cur_arg += 2;
3566 } else {
3567 /* unknown suboption - catchall */
3568 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3569 file, linenum, args[0], args[1]);
3570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
3572 }
3573 } /* end while loop */
3574 }
3575 }
3576
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003577 else if (!strcmp(args[1], "redis-check")) {
3578 /* use REDIS PING request to check servers' health */
3579 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3580 err_code |= ERR_WARN;
3581
3582 free(curproxy->check_req);
3583 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003584 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003585 curproxy->options2 |= PR_O2_REDIS_CHK;
3586
3587 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3588 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3589 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3590 }
3591
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003592 else if (!strcmp(args[1], "mysql-check")) {
3593 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003594 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3595 err_code |= ERR_WARN;
3596
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003597 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003598 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003599 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003600 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003601
3602 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3603 * const char mysql40_client_auth_pkt[] = {
3604 * "\x0e\x00\x00" // packet length
3605 * "\x01" // packet number
3606 * "\x00\x00" // client capabilities
3607 * "\x00\x00\x01" // max packet
3608 * "haproxy\x00" // username (null terminated string)
3609 * "\x00" // filler (always 0x00)
3610 * "\x01\x00\x00" // packet length
3611 * "\x00" // packet number
3612 * "\x01" // COM_QUIT command
3613 * };
3614 */
3615
3616 if (*(args[2])) {
3617 int cur_arg = 2;
3618
3619 while (*(args[cur_arg])) {
3620 if (strcmp(args[cur_arg], "user") == 0) {
3621 char *mysqluser;
3622 int packetlen, reqlen, userlen;
3623
3624 /* suboption header - needs additional argument for it */
3625 if (*(args[cur_arg+1]) == 0) {
3626 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3627 file, linenum, args[0], args[1], args[cur_arg]);
3628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
3630 }
3631 mysqluser = args[cur_arg + 1];
3632 userlen = strlen(mysqluser);
3633 packetlen = userlen + 7;
3634 reqlen = packetlen + 9;
3635
3636 free(curproxy->check_req);
3637 curproxy->check_req = (char *)calloc(1, reqlen);
3638 curproxy->check_len = reqlen;
3639
3640 snprintf(curproxy->check_req, 4, "%c%c%c",
3641 ((unsigned char) packetlen & 0xff),
3642 ((unsigned char) (packetlen >> 8) & 0xff),
3643 ((unsigned char) (packetlen >> 16) & 0xff));
3644
3645 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003646 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003647 curproxy->check_req[8] = 1;
3648 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3649 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3650 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3651 cur_arg += 2;
3652 } else {
3653 /* unknown suboption - catchall */
3654 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3655 file, linenum, args[0], args[1]);
3656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
3658 }
3659 } /* end while loop */
3660 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003661 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003662 else if (!strcmp(args[1], "ldap-check")) {
3663 /* use LDAP request to check servers' health */
3664 free(curproxy->check_req);
3665 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003666 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003667 curproxy->options2 |= PR_O2_LDAP_CHK;
3668
3669 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3670 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3671 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3672 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003673 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003674 int cur_arg;
3675
3676 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3677 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003678 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003679
Willy Tarreau87cf5142011-08-19 22:57:24 +02003680 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003681
3682 free(curproxy->fwdfor_hdr_name);
3683 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3684 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3685
3686 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3687 cur_arg = 2;
3688 while (*(args[cur_arg])) {
3689 if (!strcmp(args[cur_arg], "except")) {
3690 /* suboption except - needs additional argument for it */
3691 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3692 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3693 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003696 }
3697 /* flush useless bits */
3698 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003699 cur_arg += 2;
3700 } else if (!strcmp(args[cur_arg], "header")) {
3701 /* suboption header - needs additional argument for it */
3702 if (*(args[cur_arg+1]) == 0) {
3703 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3704 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003707 }
3708 free(curproxy->fwdfor_hdr_name);
3709 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3710 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3711 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003712 } else if (!strcmp(args[cur_arg], "if-none")) {
3713 curproxy->options &= ~PR_O_FF_ALWAYS;
3714 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003715 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003716 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003717 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003718 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003721 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003722 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003723 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003724 else if (!strcmp(args[1], "originalto")) {
3725 int cur_arg;
3726
3727 /* insert x-original-to field, but not for the IP address listed as an except.
3728 * set default options (ie: bitfield, header name, etc)
3729 */
3730
3731 curproxy->options |= PR_O_ORGTO;
3732
3733 free(curproxy->orgto_hdr_name);
3734 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3735 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3736
Willy Tarreau87cf5142011-08-19 22:57:24 +02003737 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003738 cur_arg = 2;
3739 while (*(args[cur_arg])) {
3740 if (!strcmp(args[cur_arg], "except")) {
3741 /* suboption except - needs additional argument for it */
3742 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3743 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3744 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003747 }
3748 /* flush useless bits */
3749 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3750 cur_arg += 2;
3751 } else if (!strcmp(args[cur_arg], "header")) {
3752 /* suboption header - needs additional argument for it */
3753 if (*(args[cur_arg+1]) == 0) {
3754 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3755 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003758 }
3759 free(curproxy->orgto_hdr_name);
3760 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3761 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3762 cur_arg += 2;
3763 } else {
3764 /* unknown suboption - catchall */
3765 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3766 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003769 }
3770 } /* end while loop */
3771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 else {
3773 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 }
Willy Tarreau93893792009-07-23 13:19:11 +02003777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003779 else if (!strcmp(args[0], "default_backend")) {
3780 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003782
3783 if (*(args[1]) == 0) {
3784 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003787 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003788 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003789 curproxy->defbe.name = strdup(args[1]);
3790 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003792 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003794
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003795 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3796 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 /* enable reconnections to dispatch */
3799 curproxy->options |= PR_O_REDISP;
3800 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003801 else if (!strcmp(args[0], "http-check")) {
3802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003804
3805 if (strcmp(args[1], "disable-on-404") == 0) {
3806 /* enable a graceful server shutdown on an HTTP 404 response */
3807 curproxy->options |= PR_O_DISABLE404;
3808 }
Willy Tarreauef781042010-01-27 11:53:01 +01003809 else if (strcmp(args[1], "send-state") == 0) {
3810 /* enable emission of the apparent state of a server in HTTP checks */
3811 curproxy->options2 |= PR_O2_CHK_SNDST;
3812 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003813 else if (strcmp(args[1], "expect") == 0) {
3814 const char *ptr_arg;
3815 int cur_arg;
3816
3817 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3818 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
3821 }
3822
3823 cur_arg = 2;
3824 /* consider exclamation marks, sole or at the beginning of a word */
3825 while (*(ptr_arg = args[cur_arg])) {
3826 while (*ptr_arg == '!') {
3827 curproxy->options2 ^= PR_O2_EXP_INV;
3828 ptr_arg++;
3829 }
3830 if (*ptr_arg)
3831 break;
3832 cur_arg++;
3833 }
3834 /* now ptr_arg points to the beginning of a word past any possible
3835 * exclamation mark, and cur_arg is the argument which holds this word.
3836 */
3837 if (strcmp(ptr_arg, "status") == 0) {
3838 if (!*(args[cur_arg + 1])) {
3839 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3840 file, linenum, args[0], args[1], ptr_arg);
3841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
3843 }
3844 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003845 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003846 curproxy->expect_str = strdup(args[cur_arg + 1]);
3847 }
3848 else if (strcmp(ptr_arg, "string") == 0) {
3849 if (!*(args[cur_arg + 1])) {
3850 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3851 file, linenum, args[0], args[1], ptr_arg);
3852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
3854 }
3855 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003856 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003857 curproxy->expect_str = strdup(args[cur_arg + 1]);
3858 }
3859 else if (strcmp(ptr_arg, "rstatus") == 0) {
3860 if (!*(args[cur_arg + 1])) {
3861 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3862 file, linenum, args[0], args[1], ptr_arg);
3863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
3865 }
3866 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003867 free(curproxy->expect_str);
3868 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3869 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003870 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3871 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3872 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3873 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
3876 }
3877 }
3878 else if (strcmp(ptr_arg, "rstring") == 0) {
3879 if (!*(args[cur_arg + 1])) {
3880 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3881 file, linenum, args[0], args[1], ptr_arg);
3882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
3884 }
3885 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003886 free(curproxy->expect_str);
3887 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3888 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003889 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3890 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3891 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3892 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
3895 }
3896 }
3897 else {
3898 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3899 file, linenum, args[0], args[1], ptr_arg);
3900 err_code |= ERR_ALERT | ERR_FATAL;
3901 goto out;
3902 }
3903 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003904 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003905 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 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003908 }
3909 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003910 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003911 if (curproxy == &defproxy) {
3912 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003915 }
3916
Willy Tarreaub80c2302007-11-30 20:51:32 +01003917 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003919
3920 if (strcmp(args[1], "fail") == 0) {
3921 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003922 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003923 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3924 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003927 }
3928
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003929 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3930 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3931 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003934 }
3935 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3936 }
3937 else {
3938 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003941 }
3942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943#ifdef TPROXY
3944 else if (!strcmp(args[0], "transparent")) {
3945 /* enable transparent proxy connections */
3946 curproxy->options |= PR_O_TRANSP;
3947 }
3948#endif
3949 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003950 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003952
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953 if (*(args[1]) == 0) {
3954 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003957 }
3958 curproxy->maxconn = atol(args[1]);
3959 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003960 else if (!strcmp(args[0], "backlog")) { /* backlog */
3961 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003962 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003963
3964 if (*(args[1]) == 0) {
3965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003968 }
3969 curproxy->backlog = atol(args[1]);
3970 }
Willy Tarreau86034312006-12-29 00:10:33 +01003971 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003972 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003973 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003974
Willy Tarreau86034312006-12-29 00:10:33 +01003975 if (*(args[1]) == 0) {
3976 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003977 err_code |= ERR_ALERT | ERR_FATAL;
3978 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003979 }
3980 curproxy->fullconn = atol(args[1]);
3981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003982 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3983 if (*(args[1]) == 0) {
3984 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003987 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003988 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3989 if (err) {
3990 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3991 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003994 }
3995 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 }
3997 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003998 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003999 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004000 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004001
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002 if (curproxy == &defproxy) {
4003 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004004 err_code |= ERR_ALERT | ERR_FATAL;
4005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004007 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004009
Willy Tarreau902636f2013-03-10 19:44:48 +01004010 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004011 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004012 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004013 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004014 goto out;
4015 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004016
4017 proto = protocol_by_family(sk->ss_family);
4018 if (!proto || !proto->connect) {
4019 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4020 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
4023 }
4024
4025 if (port1 != port2) {
4026 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4027 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004031
4032 if (!port1) {
4033 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4034 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004038
Willy Tarreaud5191e72010-02-09 20:50:45 +01004039 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004040 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 }
4042 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004043 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004044 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004045
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004046 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4047 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004052 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4053 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4054 err_code |= ERR_WARN;
4055
4056 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4057 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4058 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4059 }
4060 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4061 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4062 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4063 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004064 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4065 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4066 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4067 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004068 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004069 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004070 err_code |= ERR_ALERT | ERR_FATAL;
4071 goto out;
4072 }
4073 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004074 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004075 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004076 short realport = 0;
4077 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004079 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004080 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004083 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004084 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004085 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086
4087 if (!*args[2]) {
4088 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4089 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004093
4094 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004095 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004096 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4097 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004100 }
4101
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004102 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004103 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004104 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004105 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004106
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004107 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4108 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4109 err_code |= ERR_ALERT | ERR_ABORT;
4110 goto out;
4111 }
4112
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004113 /* the servers are linked backwards first */
4114 newsrv->next = curproxy->srv;
4115 curproxy->srv = newsrv;
4116 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004117 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004118 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004119
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004120 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004121 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004122 LIST_INIT(&newsrv->pendconns);
4123 do_check = 0;
4124 newsrv->state = SRV_RUNNING; /* early server setup */
4125 newsrv->last_change = now.tv_sec;
4126 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004128 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004129 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004130 * - IP: => port=+0, relative
4131 * - IP:N => port=N, absolute
4132 * - IP:+N => port=+N, relative
4133 * - IP:-N => port=-N, relative
4134 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004135 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004136 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004137 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004138 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004139 goto out;
4140 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004141
4142 proto = protocol_by_family(sk->ss_family);
4143 if (!proto || !proto->connect) {
4144 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4145 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004146 err_code |= ERR_ALERT | ERR_FATAL;
4147 goto out;
4148 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004149
4150 if (!port1 || !port2) {
4151 /* no port specified, +offset, -offset */
4152 newsrv->state |= SRV_MAPPORTS;
4153 }
4154 else if (port1 != port2) {
4155 /* port range */
4156 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4157 file, linenum, args[0], args[1], args[2]);
4158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
4160 }
4161 else {
4162 /* used by checks */
4163 realport = port1;
4164 }
4165
Willy Tarreaud5191e72010-02-09 20:50:45 +01004166 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004167 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4168 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004169
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004170 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004171 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4172 file, linenum, newsrv->addr.ss_family, args[2]);
4173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
4175 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004176
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004177 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004178 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004179 newsrv->inter = curproxy->defsrv.inter;
4180 newsrv->fastinter = curproxy->defsrv.fastinter;
4181 newsrv->downinter = curproxy->defsrv.downinter;
4182 newsrv->rise = curproxy->defsrv.rise;
4183 newsrv->fall = curproxy->defsrv.fall;
4184 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4185 newsrv->minconn = curproxy->defsrv.minconn;
4186 newsrv->maxconn = curproxy->defsrv.maxconn;
4187 newsrv->slowstart = curproxy->defsrv.slowstart;
4188 newsrv->onerror = curproxy->defsrv.onerror;
4189 newsrv->consecutive_errors_limit
4190 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004191#ifdef OPENSSL
4192 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4193#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004194 newsrv->uweight = newsrv->iweight
4195 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004197 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004198
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004199 cur_arg = 3;
4200 } else {
4201 newsrv = &curproxy->defsrv;
4202 cur_arg = 1;
4203 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004204
Willy Tarreaubaaee002006-06-26 02:48:02 +02004205 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004206 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004207 newsrv->cookie = strdup(args[cur_arg + 1]);
4208 newsrv->cklen = strlen(args[cur_arg + 1]);
4209 cur_arg += 2;
4210 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004211 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004212 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4213 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4214 cur_arg += 2;
4215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004216 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004217 if (!*args[cur_arg + 1]) {
4218 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4219 file, linenum, args[cur_arg]);
4220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
4222 }
4223
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004225 if (newsrv->rise <= 0) {
4226 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4227 file, linenum, args[cur_arg]);
4228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
4230 }
4231
Willy Tarreau96839092010-03-29 10:02:24 +02004232 if (newsrv->health)
4233 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004234 cur_arg += 2;
4235 }
4236 else if (!strcmp(args[cur_arg], "fall")) {
4237 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004238
4239 if (!*args[cur_arg + 1]) {
4240 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4241 file, linenum, args[cur_arg]);
4242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
4244 }
4245
4246 if (newsrv->fall <= 0) {
4247 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4248 file, linenum, args[cur_arg]);
4249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
4251 }
4252
Willy Tarreaubaaee002006-06-26 02:48:02 +02004253 cur_arg += 2;
4254 }
4255 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004256 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4257 if (err) {
4258 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4259 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004260 err_code |= ERR_ALERT | ERR_FATAL;
4261 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004262 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004263 if (val <= 0) {
4264 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4265 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004268 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004269 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004270 cur_arg += 2;
4271 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004272 else if (!strcmp(args[cur_arg], "fastinter")) {
4273 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4274 if (err) {
4275 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4276 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004279 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004280 if (val <= 0) {
4281 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4282 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004285 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004286 newsrv->fastinter = val;
4287 cur_arg += 2;
4288 }
4289 else if (!strcmp(args[cur_arg], "downinter")) {
4290 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4291 if (err) {
4292 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4293 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004296 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004297 if (val <= 0) {
4298 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4299 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004302 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004303 newsrv->downinter = val;
4304 cur_arg += 2;
4305 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004306 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004307 struct sockaddr_storage *sk;
4308 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004309 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004310
Willy Tarreau902636f2013-03-10 19:44:48 +01004311 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004312 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004313 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004314 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004315 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004316 goto out;
4317 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004318
4319 proto = protocol_by_family(sk->ss_family);
4320 if (!proto || !proto->connect) {
4321 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004322 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
4325 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004326
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004327 if (port1 != port2) {
4328 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4329 file, linenum, args[cur_arg], args[cur_arg + 1]);
4330 err_code |= ERR_ALERT | ERR_FATAL;
4331 goto out;
4332 }
4333
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004334 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004335 cur_arg += 2;
4336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004337 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004338 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 cur_arg += 2;
4340 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004341 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342 newsrv->state |= SRV_BACKUP;
4343 cur_arg ++;
4344 }
Simon Hormanfa461682011-06-25 09:39:49 +09004345 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4346 newsrv->state |= SRV_NON_STICK;
4347 cur_arg ++;
4348 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004349 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4350 newsrv->state |= SRV_SEND_PROXY;
4351 cur_arg ++;
4352 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004353 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4354 newsrv->check.send_proxy = 1;
4355 cur_arg ++;
4356 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004357 else if (!strcmp(args[cur_arg], "weight")) {
4358 int w;
4359 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004360 if (w < 0 || w > 256) {
4361 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004362 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004363 err_code |= ERR_ALERT | ERR_FATAL;
4364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004365 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004366 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004367 cur_arg += 2;
4368 }
4369 else if (!strcmp(args[cur_arg], "minconn")) {
4370 newsrv->minconn = atol(args[cur_arg + 1]);
4371 cur_arg += 2;
4372 }
4373 else if (!strcmp(args[cur_arg], "maxconn")) {
4374 newsrv->maxconn = atol(args[cur_arg + 1]);
4375 cur_arg += 2;
4376 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004377 else if (!strcmp(args[cur_arg], "maxqueue")) {
4378 newsrv->maxqueue = atol(args[cur_arg + 1]);
4379 cur_arg += 2;
4380 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004381 else if (!strcmp(args[cur_arg], "slowstart")) {
4382 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004383 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004384 if (err) {
4385 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4386 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004389 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004390 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004391 cur_arg += 2;
4392 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004393 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004394
4395 if (!*args[cur_arg + 1]) {
4396 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4397 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004400 }
4401
4402 newsrv->trackit = strdup(args[cur_arg + 1]);
4403
4404 cur_arg += 2;
4405 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004406 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004407 global.maxsock++;
4408 do_check = 1;
4409 cur_arg += 1;
4410 }
Willy Tarreau96839092010-03-29 10:02:24 +02004411 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4412 newsrv->state |= SRV_MAINTAIN;
4413 newsrv->state &= ~SRV_RUNNING;
4414 newsrv->health = 0;
4415 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004416 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004417 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004418 if (!strcmp(args[cur_arg + 1], "none"))
4419 newsrv->observe = HANA_OBS_NONE;
4420 else if (!strcmp(args[cur_arg + 1], "layer4"))
4421 newsrv->observe = HANA_OBS_LAYER4;
4422 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4423 if (curproxy->mode != PR_MODE_HTTP) {
4424 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4425 file, linenum, args[cur_arg + 1]);
4426 err_code |= ERR_ALERT;
4427 }
4428 newsrv->observe = HANA_OBS_LAYER7;
4429 }
4430 else {
4431 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004432 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004433 file, linenum, args[cur_arg], args[cur_arg + 1]);
4434 err_code |= ERR_ALERT | ERR_FATAL;
4435 goto out;
4436 }
4437
4438 cur_arg += 2;
4439 }
4440 else if (!strcmp(args[cur_arg], "on-error")) {
4441 if (!strcmp(args[cur_arg + 1], "fastinter"))
4442 newsrv->onerror = HANA_ONERR_FASTINTER;
4443 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4444 newsrv->onerror = HANA_ONERR_FAILCHK;
4445 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4446 newsrv->onerror = HANA_ONERR_SUDDTH;
4447 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4448 newsrv->onerror = HANA_ONERR_MARKDWN;
4449 else {
4450 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004451 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004452 file, linenum, args[cur_arg], args[cur_arg + 1]);
4453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 }
4456
4457 cur_arg += 2;
4458 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004459 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4460 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4461 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4462 else {
4463 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4464 file, linenum, args[cur_arg], args[cur_arg + 1]);
4465 err_code |= ERR_ALERT | ERR_FATAL;
4466 goto out;
4467 }
4468
4469 cur_arg += 2;
4470 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004471 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4472 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4473 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4474 else {
4475 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4476 file, linenum, args[cur_arg], args[cur_arg + 1]);
4477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
4479 }
4480
4481 cur_arg += 2;
4482 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004483 else if (!strcmp(args[cur_arg], "error-limit")) {
4484 if (!*args[cur_arg + 1]) {
4485 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4486 file, linenum, args[cur_arg]);
4487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
4489 }
4490
4491 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4492
4493 if (newsrv->consecutive_errors_limit <= 0) {
4494 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4495 file, linenum, args[cur_arg]);
4496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
4498 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004499 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004500 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004501 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004502 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004503 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004504 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004505
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004507 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4508 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004509 err_code |= ERR_ALERT | ERR_FATAL;
4510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004512
Willy Tarreauef9a3602012-12-08 22:29:20 +01004513 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004514 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004515 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004516 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004517 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004518 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004519 goto out;
4520 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004521
4522 proto = protocol_by_family(sk->ss_family);
4523 if (!proto || !proto->connect) {
4524 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4525 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004526 err_code |= ERR_ALERT | ERR_FATAL;
4527 goto out;
4528 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004529
Willy Tarreauef9a3602012-12-08 22:29:20 +01004530 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004531
4532 if (port_low != port_high) {
4533 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004534
4535 if (!port_low || !port_high) {
4536 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4537 file, linenum, args[cur_arg], args[cur_arg + 1]);
4538 err_code |= ERR_ALERT | ERR_FATAL;
4539 goto out;
4540 }
4541
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004542 if (port_low <= 0 || port_low > 65535 ||
4543 port_high <= 0 || port_high > 65535 ||
4544 port_low > port_high) {
4545 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4546 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004549 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004550 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4551 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4552 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004553 }
4554
Willy Tarreaubaaee002006-06-26 02:48:02 +02004555 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004556 while (*(args[cur_arg])) {
4557 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004558#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4559#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004560 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004561 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4562 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004563 err_code |= ERR_ALERT | ERR_FATAL;
4564 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004565 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004566#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004567 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004568 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004569 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004570 err_code |= ERR_ALERT | ERR_FATAL;
4571 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004572 }
4573 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004574 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4575 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004576 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004577 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4578 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004579 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4580 char *name, *end;
4581
4582 name = args[cur_arg+1] + 7;
4583 while (isspace(*name))
4584 name++;
4585
4586 end = name;
4587 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4588 end++;
4589
Willy Tarreauef9a3602012-12-08 22:29:20 +01004590 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4591 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4592 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4593 newsrv->conn_src.bind_hdr_len = end - name;
4594 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4595 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4596 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004597
4598 /* now look for an occurrence number */
4599 while (isspace(*end))
4600 end++;
4601 if (*end == ',') {
4602 end++;
4603 name = end;
4604 if (*end == '-')
4605 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004606 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004607 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004608 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004609 }
4610
Willy Tarreauef9a3602012-12-08 22:29:20 +01004611 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004612 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4613 " occurrences values smaller than %d.\n",
4614 file, linenum, MAX_HDR_HISTORY);
4615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
4617 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004618 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004619 struct sockaddr_storage *sk;
4620 int port1, port2;
4621
Willy Tarreau902636f2013-03-10 19:44:48 +01004622 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004623 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004624 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004625 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004626 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004627 goto out;
4628 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004629
4630 proto = protocol_by_family(sk->ss_family);
4631 if (!proto || !proto->connect) {
4632 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4633 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004634 err_code |= ERR_ALERT | ERR_FATAL;
4635 goto out;
4636 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004637
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004638 if (port1 != port2) {
4639 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4640 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004644 newsrv->conn_src.tproxy_addr = *sk;
4645 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004646 }
4647 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004648#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004649 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004650#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004651 cur_arg += 2;
4652 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004653#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004654 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004655 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004656 err_code |= ERR_ALERT | ERR_FATAL;
4657 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004658#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4659 } /* "usesrc" */
4660
4661 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4662#ifdef SO_BINDTODEVICE
4663 if (!*args[cur_arg + 1]) {
4664 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4665 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004668 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004669 free(newsrv->conn_src.iface_name);
4670 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4671 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004672 global.last_checks |= LSTCHK_NETADM;
4673#else
4674 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4675 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004676 err_code |= ERR_ALERT | ERR_FATAL;
4677 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004678#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004679 cur_arg += 2;
4680 continue;
4681 }
4682 /* this keyword in not an option of "source" */
4683 break;
4684 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004686 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004687 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4688 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004693 static int srv_dumped;
4694 struct srv_kw *kw;
4695 char *err;
4696
4697 kw = srv_find_kw(args[cur_arg]);
4698 if (kw) {
4699 char *err = NULL;
4700 int code;
4701
4702 if (!kw->parse) {
4703 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4704 file, linenum, args[0], args[1], args[cur_arg]);
4705 cur_arg += 1 + kw->skip ;
4706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
4708 }
4709
4710 if (defsrv && !kw->default_ok) {
4711 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4712 file, linenum, args[0], args[1], args[cur_arg]);
4713 cur_arg += 1 + kw->skip ;
4714 err_code |= ERR_ALERT;
4715 continue;
4716 }
4717
4718 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4719 err_code |= code;
4720
4721 if (code) {
4722 if (err && *err) {
4723 indent_msg(&err, 2);
4724 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4725 }
4726 else
4727 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4728 file, linenum, args[0], args[1], args[cur_arg]);
4729 if (code & ERR_FATAL) {
4730 free(err);
4731 cur_arg += 1 + kw->skip;
4732 goto out;
4733 }
4734 }
4735 free(err);
4736 cur_arg += 1 + kw->skip;
4737 continue;
4738 }
4739
4740 err = NULL;
4741 if (!srv_dumped) {
4742 srv_dump_kws(&err);
4743 indent_msg(&err, 4);
4744 srv_dumped = 1;
4745 }
4746
4747 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4748 file, linenum, args[0], args[1], args[cur_arg],
4749 err ? " Registered keywords :" : "", err ? err : "");
4750 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004751
Willy Tarreau93893792009-07-23 13:19:11 +02004752 err_code |= ERR_ALERT | ERR_FATAL;
4753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754 }
4755 }
4756
4757 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004758 if (newsrv->trackit) {
4759 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4760 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004763 }
4764
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004765 /* If neither a port nor an addr was specified and no check transport
4766 * layer is forced, then the transport layer used by the checks is the
4767 * same as for the production traffic. Otherwise we use raw_sock by
4768 * default, unless one is specified.
4769 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004770 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004771#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004772 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004773#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004774 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4775 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004776 /* try to get the port from check.addr if check.port not set */
4777 if (!newsrv->check.port)
4778 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004779
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004780 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004781 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004782
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004783 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004784 /* not yet valid, because no port was set on
4785 * the server either. We'll check if we have
4786 * a known port on the first listener.
4787 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004788 struct listener *l;
4789
4790 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004791 newsrv->check.port = get_host_port(&l->addr);
4792 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004793 break;
4794 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004795 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004796 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004797 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4798 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004801 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004802
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004803 /* Allocate buffer for check requests... */
4804 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004805 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4806 err_code |= ERR_ALERT | ERR_ABORT;
4807 goto out;
4808 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004809 newsrv->check.bi->size = global.tune.chksize;
4810
4811 /* Allocate buffer for check responses... */
4812 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4813 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4814 err_code |= ERR_ALERT | ERR_ABORT;
4815 goto out;
4816 }
4817 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004818
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004819 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004820 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004821 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4822 err_code |= ERR_ALERT | ERR_ABORT;
4823 goto out;
4824 }
4825
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004826 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4827 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004828 newsrv->state |= SRV_CHECKED;
4829 }
4830
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004831 if (!defsrv) {
4832 if (newsrv->state & SRV_BACKUP)
4833 curproxy->srv_bck++;
4834 else
4835 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004836
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004837 newsrv->prev_state = newsrv->state;
4838 }
William Lallemanda73203e2012-03-12 12:48:57 +01004839 }
4840
4841 else if (strcmp(args[0], "unique-id-format") == 0) {
4842 if (!*(args[1])) {
4843 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
4846 }
William Lallemand3203ff42012-11-11 17:30:56 +01004847 if (*(args[2])) {
4848 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004852 free(curproxy->conf.uniqueid_format_string);
4853 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004854
Willy Tarreau62a61232013-04-12 18:13:46 +02004855 free(curproxy->conf.uif_file);
4856 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4857 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004858 }
William Lallemanda73203e2012-03-12 12:48:57 +01004859
4860 else if (strcmp(args[0], "unique-id-header") == 0) {
4861 if (!*(args[1])) {
4862 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4863 err_code |= ERR_ALERT | ERR_FATAL;
4864 goto out;
4865 }
4866 free(curproxy->header_unique_id);
4867 curproxy->header_unique_id = strdup(args[1]);
4868 }
4869
William Lallemand723b73a2012-02-08 16:37:49 +01004870 else if (strcmp(args[0], "log-format") == 0) {
4871 if (!*(args[1])) {
4872 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
4875 }
William Lallemand3203ff42012-11-11 17:30:56 +01004876 if (*(args[2])) {
4877 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
4880 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004881
Willy Tarreau62a61232013-04-12 18:13:46 +02004882 if (curproxy->conf.logformat_string != default_http_log_format &&
4883 curproxy->conf.logformat_string != default_tcp_log_format &&
4884 curproxy->conf.logformat_string != clf_http_log_format)
4885 free(curproxy->conf.logformat_string);
4886 curproxy->conf.logformat_string = strdup(args[1]);
4887
4888 free(curproxy->conf.lfs_file);
4889 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4890 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004891
4892 /* get a chance to improve log-format error reporting by
4893 * reporting the correct line-number when possible.
4894 */
4895 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4896 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4897 file, linenum, curproxy->id);
4898 err_code |= ERR_WARN;
4899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
William Lallemand723b73a2012-02-08 16:37:49 +01004901
William Lallemand0f99e342011-10-12 17:50:54 +02004902 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4903 /* delete previous herited or defined syslog servers */
4904 struct logsrv *back;
4905
4906 if (*(args[1]) != 0) {
4907 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
4910 }
4911
William Lallemand723b73a2012-02-08 16:37:49 +01004912 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4913 LIST_DEL(&tmplogsrv->list);
4914 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004915 }
4916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004918 struct logsrv *logsrv;
4919
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004921 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004922 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004923 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004924 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004925 LIST_INIT(&node->list);
4926 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4927 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 }
4929 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004930 struct sockaddr_storage *sk;
4931 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004932
4933 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004934
William Lallemand0f99e342011-10-12 17:50:54 +02004935 logsrv->facility = get_log_facility(args[2]);
4936 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
4940
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 }
4942
William Lallemand0f99e342011-10-12 17:50:54 +02004943 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004945 logsrv->level = get_log_level(args[3]);
4946 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
4950
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952 }
4953
William Lallemand0f99e342011-10-12 17:50:54 +02004954 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004955 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004956 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004957 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004958 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004959 err_code |= ERR_ALERT | ERR_FATAL;
4960 goto out;
4961
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004962 }
4963 }
4964
Willy Tarreau902636f2013-03-10 19:44:48 +01004965 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004966 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004967 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004968 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004969 goto out;
4970 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004971
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004972 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004973
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004974 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004975 if (port1 != port2) {
4976 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4977 file, linenum, args[0], args[1]);
4978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
4980 }
4981
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004982 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004983 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 }
William Lallemand0f99e342011-10-12 17:50:54 +02004985
4986 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 }
4988 else {
4989 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4990 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
4994 }
4995 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004996 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004997 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004998 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004999 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005000
Willy Tarreau977b8e42006-12-29 14:19:17 +01005001 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005002 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005003
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005005 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5006 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005010
5011 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005012 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5013 free(curproxy->conn_src.iface_name);
5014 curproxy->conn_src.iface_name = NULL;
5015 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005016
Willy Tarreau902636f2013-03-10 19:44:48 +01005017 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005018 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005019 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005020 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005021 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005022 goto out;
5023 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005024
5025 proto = protocol_by_family(sk->ss_family);
5026 if (!proto || !proto->connect) {
5027 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005028 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005029 err_code |= ERR_ALERT | ERR_FATAL;
5030 goto out;
5031 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005032
5033 if (port1 != port2) {
5034 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5035 file, linenum, args[0], args[1]);
5036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
5038 }
5039
Willy Tarreauef9a3602012-12-08 22:29:20 +01005040 curproxy->conn_src.source_addr = *sk;
5041 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005042
5043 cur_arg = 2;
5044 while (*(args[cur_arg])) {
5045 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005046#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
5047#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005048 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005049 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5050 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005053 }
5054#endif
5055 if (!*args[cur_arg + 1]) {
5056 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5057 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005060 }
5061
5062 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005063 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5064 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005065 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005066 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5067 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005068 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5069 char *name, *end;
5070
5071 name = args[cur_arg+1] + 7;
5072 while (isspace(*name))
5073 name++;
5074
5075 end = name;
5076 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5077 end++;
5078
Willy Tarreauef9a3602012-12-08 22:29:20 +01005079 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5080 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5081 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5082 curproxy->conn_src.bind_hdr_len = end - name;
5083 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5084 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5085 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005086
5087 /* now look for an occurrence number */
5088 while (isspace(*end))
5089 end++;
5090 if (*end == ',') {
5091 end++;
5092 name = end;
5093 if (*end == '-')
5094 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005095 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005096 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005097 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005098 }
5099
Willy Tarreauef9a3602012-12-08 22:29:20 +01005100 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005101 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5102 " occurrences values smaller than %d.\n",
5103 file, linenum, MAX_HDR_HISTORY);
5104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
5106 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005107 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005108 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005109
Willy Tarreau902636f2013-03-10 19:44:48 +01005110 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005111 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005112 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005113 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005114 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005115 goto out;
5116 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005117
5118 proto = protocol_by_family(sk->ss_family);
5119 if (!proto || !proto->connect) {
5120 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5121 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
5124 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005125
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005126 if (port1 != port2) {
5127 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5128 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
5131 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005132 curproxy->conn_src.tproxy_addr = *sk;
5133 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005134 }
5135 global.last_checks |= LSTCHK_NETADM;
5136#if !defined(CONFIG_HAP_LINUX_TPROXY)
5137 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005138#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005139#else /* no TPROXY support */
5140 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005141 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005144#endif
5145 cur_arg += 2;
5146 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005147 }
5148
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005149 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5150#ifdef SO_BINDTODEVICE
5151 if (!*args[cur_arg + 1]) {
5152 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005156 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005157 free(curproxy->conn_src.iface_name);
5158 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5159 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005160 global.last_checks |= LSTCHK_NETADM;
5161#else
5162 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5163 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005166#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005167 cur_arg += 2;
5168 continue;
5169 }
5170 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005171 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005174 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005176 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5177 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5178 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005183 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5185 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189
5190 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005191 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005192 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005193 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 }
5196 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005197 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005198 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005199 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 }
5203 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005205 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005206 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005207 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 }
5210 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005211 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005212 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005213 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005214 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216 }
5217 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005218 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005219 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005220 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005221 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005224 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005225 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005226 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005227 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005229 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005230 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005231 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005232 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005233 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005234 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005235 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005236 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005237 }
5238 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005240 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005241 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005243 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005245 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5248 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005251 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252
5253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005254 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005255 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
5259 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005260 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005261 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005262 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 }
5266 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005268 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005269 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
5273 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005275 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005276 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
5280 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005281 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005282 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005283 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005287 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005288 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005289 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005290 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005292 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005295 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005296
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297 if (curproxy == &defproxy) {
5298 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005302 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005303 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 if (*(args[1]) == 0) {
5306 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005310
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005311 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005312 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5313 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5314 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
5317 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005318 err_code |= warnif_cond_conflicts(cond,
5319 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5320 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005321 }
5322 else if (*args[2]) {
5323 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5324 file, linenum, args[0], args[2]);
5325 err_code |= ERR_ALERT | ERR_FATAL;
5326 goto out;
5327 }
5328
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005329 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005330 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005331 wl->s = strdup(args[1]);
5332 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005333 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 }
5335 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005336 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5338 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005342
Willy Tarreauade5ec42010-01-28 19:33:49 +01005343 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005344 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005345 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005346 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 }
5349 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005350 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005351 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005352 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005355 }
5356 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005357 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005358 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005359 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005360 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 }
5363 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005364 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5366 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 }
5370
Willy Tarreauade5ec42010-01-28 19:33:49 +01005371 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005372 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005373 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005374 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 }
5377 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005378 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005379 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005380 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005381 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 }
5384 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005385 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005386 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005387 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005388 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 }
5391 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005392 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005393
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 if (curproxy == &defproxy) {
5395 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005399 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005400 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402 if (*(args[1]) == 0) {
5403 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005406 }
5407
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005408 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005409 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5410 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5411 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005412 err_code |= ERR_ALERT | ERR_FATAL;
5413 goto out;
5414 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005415 err_code |= warnif_cond_conflicts(cond,
5416 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5417 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005418 }
5419 else if (*args[2]) {
5420 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5421 file, linenum, args[0], args[2]);
5422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
5424 }
5425
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005426 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005427 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005428 wl->s = strdup(args[1]);
5429 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005430 }
5431 else if (!strcmp(args[0], "errorloc") ||
5432 !strcmp(args[0], "errorloc302") ||
5433 !strcmp(args[0], "errorloc303")) { /* error location */
5434 int errnum, errlen;
5435 char *err;
5436
Willy Tarreau977b8e42006-12-29 14:19:17 +01005437 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005438 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005439
Willy Tarreaubaaee002006-06-26 02:48:02 +02005440 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005441 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005444 }
5445
5446 errnum = atol(args[1]);
5447 if (!strcmp(args[0], "errorloc303")) {
5448 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5449 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5450 } else {
5451 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5452 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5453 }
5454
Willy Tarreau0f772532006-12-23 20:51:41 +01005455 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5456 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005457 chunk_destroy(&curproxy->errmsg[rc]);
5458 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005459 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005462
5463 if (rc >= HTTP_ERR_SIZE) {
5464 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5465 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466 free(err);
5467 }
5468 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005469 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5470 int errnum, errlen, fd;
5471 char *err;
5472 struct stat stat;
5473
5474 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005475 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005476
5477 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005478 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005479 err_code |= ERR_ALERT | ERR_FATAL;
5480 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005481 }
5482
5483 fd = open(args[2], O_RDONLY);
5484 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5485 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5486 file, linenum, args[2], args[1]);
5487 if (fd >= 0)
5488 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005491 }
5492
Willy Tarreau27a674e2009-08-17 07:23:33 +02005493 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005494 errlen = stat.st_size;
5495 } else {
5496 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005497 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005498 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005499 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005500 }
5501
5502 err = malloc(errlen); /* malloc() must succeed during parsing */
5503 errnum = read(fd, err, errlen);
5504 if (errnum != errlen) {
5505 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5506 file, linenum, args[2], args[1]);
5507 close(fd);
5508 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005509 err_code |= ERR_ALERT | ERR_FATAL;
5510 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005511 }
5512 close(fd);
5513
5514 errnum = atol(args[1]);
5515 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5516 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005517 chunk_destroy(&curproxy->errmsg[rc]);
5518 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005519 break;
5520 }
5521 }
5522
5523 if (rc >= HTTP_ERR_SIZE) {
5524 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5525 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005526 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005527 free(err);
5528 }
5529 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005530 else if (!strcmp(args[0], "compression")) {
5531 struct comp *comp;
5532 if (curproxy->comp == NULL) {
5533 comp = calloc(1, sizeof(struct comp));
5534 curproxy->comp = comp;
5535 } else {
5536 comp = curproxy->comp;
5537 }
5538
5539 if (!strcmp(args[1], "algo")) {
5540 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005541 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005542
William Lallemand82fe75c2012-10-23 10:25:10 +02005543 cur_arg = 2;
5544 if (!*args[cur_arg]) {
5545 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5546 file, linenum, args[0]);
5547 err_code |= ERR_ALERT | ERR_FATAL;
5548 goto out;
5549 }
5550 while (*(args[cur_arg])) {
5551 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5552 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5553 file, linenum, args[0], args[cur_arg]);
5554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
5556 }
William Lallemand552df672012-11-07 13:21:47 +01005557 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5558 curproxy->comp->algos->end(&ctx);
5559 } else {
5560 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5561 file, linenum, args[0], args[cur_arg]);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005565 cur_arg ++;
5566 continue;
5567 }
5568 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005569 else if (!strcmp(args[1], "offload")) {
5570 comp->offload = 1;
5571 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005572 else if (!strcmp(args[1], "type")) {
5573 int cur_arg;
5574 cur_arg = 2;
5575 if (!*args[cur_arg]) {
5576 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5577 file, linenum, args[0]);
5578 err_code |= ERR_ALERT | ERR_FATAL;
5579 goto out;
5580 }
5581 while (*(args[cur_arg])) {
5582 comp_append_type(comp, args[cur_arg]);
5583 cur_arg ++;
5584 continue;
5585 }
5586 }
5587 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005588 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005589 file, linenum, args[0]);
5590 err_code |= ERR_ALERT | ERR_FATAL;
5591 goto out;
5592 }
5593 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005595 struct cfg_kw_list *kwl;
5596 int index;
5597
5598 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5599 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5600 if (kwl->kw[index].section != CFG_LISTEN)
5601 continue;
5602 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5603 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005604 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005605 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005606 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005607 err_code |= ERR_ALERT | ERR_FATAL;
5608 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005609 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005610 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005611 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005612 err_code |= ERR_WARN;
5613 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005614 }
Willy Tarreau93893792009-07-23 13:19:11 +02005615 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005616 }
5617 }
5618 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005619
Willy Tarreau6daf3432008-01-22 16:44:08 +01005620 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005621 err_code |= ERR_ALERT | ERR_FATAL;
5622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623 }
Willy Tarreau93893792009-07-23 13:19:11 +02005624 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005625 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005626 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627}
5628
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005629int
5630cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5631{
5632
5633 int err_code = 0;
5634 const char *err;
5635
5636 if (!strcmp(args[0], "userlist")) { /* new userlist */
5637 struct userlist *newul;
5638
5639 if (!*args[1]) {
5640 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5641 file, linenum, args[0]);
5642 err_code |= ERR_ALERT | ERR_FATAL;
5643 goto out;
5644 }
5645
5646 err = invalid_char(args[1]);
5647 if (err) {
5648 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5649 file, linenum, *err, args[0], args[1]);
5650 err_code |= ERR_ALERT | ERR_FATAL;
5651 goto out;
5652 }
5653
5654 for (newul = userlist; newul; newul = newul->next)
5655 if (!strcmp(newul->name, args[1])) {
5656 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5657 file, linenum, args[1]);
5658 err_code |= ERR_WARN;
5659 goto out;
5660 }
5661
5662 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5663 if (!newul) {
5664 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5665 err_code |= ERR_ALERT | ERR_ABORT;
5666 goto out;
5667 }
5668
5669 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5670 newul->name = strdup(args[1]);
5671
5672 if (!newul->groupusers | !newul->name) {
5673 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5674 err_code |= ERR_ALERT | ERR_ABORT;
5675 goto out;
5676 }
5677
5678 newul->next = userlist;
5679 userlist = newul;
5680
5681 } else if (!strcmp(args[0], "group")) { /* new group */
5682 int cur_arg, i;
5683 const char *err;
5684
5685 if (!*args[1]) {
5686 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5687 file, linenum, args[0]);
5688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
5690 }
5691
5692 err = invalid_char(args[1]);
5693 if (err) {
5694 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5695 file, linenum, *err, args[0], args[1]);
5696 err_code |= ERR_ALERT | ERR_FATAL;
5697 goto out;
5698 }
5699
5700 for(i = 0; i < userlist->grpcnt; i++)
5701 if (!strcmp(userlist->groups[i], args[1])) {
5702 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5703 file, linenum, args[1], userlist->name);
5704 err_code |= ERR_ALERT;
5705 goto out;
5706 }
5707
5708 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5709 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5710 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5711 err_code |= ERR_ALERT | ERR_FATAL;
5712 goto out;
5713 }
5714
5715 cur_arg = 2;
5716
5717 while (*args[cur_arg]) {
5718 if (!strcmp(args[cur_arg], "users")) {
5719 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5720 cur_arg += 2;
5721 continue;
5722 } else {
5723 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5724 file, linenum, args[0]);
5725 err_code |= ERR_ALERT | ERR_FATAL;
5726 goto out;
5727 }
5728 }
5729
5730 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5731 } else if (!strcmp(args[0], "user")) { /* new user */
5732 struct auth_users *newuser;
5733 int cur_arg;
5734
5735 if (!*args[1]) {
5736 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5737 file, linenum, args[0]);
5738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
5740 }
5741
5742 for (newuser = userlist->users; newuser; newuser = newuser->next)
5743 if (!strcmp(newuser->user, args[1])) {
5744 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5745 file, linenum, args[1], userlist->name);
5746 err_code |= ERR_ALERT;
5747 goto out;
5748 }
5749
5750 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5751 if (!newuser) {
5752 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5753 err_code |= ERR_ALERT | ERR_ABORT;
5754 goto out;
5755 }
5756
5757 newuser->user = strdup(args[1]);
5758
5759 newuser->next = userlist->users;
5760 userlist->users = newuser;
5761
5762 cur_arg = 2;
5763
5764 while (*args[cur_arg]) {
5765 if (!strcmp(args[cur_arg], "password")) {
5766#ifndef CONFIG_HAP_CRYPT
5767 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5768 file, linenum);
5769 err_code |= ERR_ALERT;
5770#endif
5771 newuser->pass = strdup(args[cur_arg + 1]);
5772 cur_arg += 2;
5773 continue;
5774 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5775 newuser->pass = strdup(args[cur_arg + 1]);
5776 newuser->flags |= AU_O_INSECURE;
5777 cur_arg += 2;
5778 continue;
5779 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005780 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005781 cur_arg += 2;
5782 continue;
5783 } else {
5784 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5785 file, linenum, args[0]);
5786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
5788 }
5789 }
5790 } else {
5791 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5792 err_code |= ERR_ALERT | ERR_FATAL;
5793 }
5794
5795out:
5796 return err_code;
5797}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798
5799/*
5800 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005801 * Returns the error code, 0 if OK, or any combination of :
5802 * - ERR_ABORT: must abort ASAP
5803 * - ERR_FATAL: we can continue parsing but not start the service
5804 * - ERR_WARN: a warning has been emitted
5805 * - ERR_ALERT: an alert has been emitted
5806 * Only the two first ones can stop processing, the two others are just
5807 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005809int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005811 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812 FILE *f;
5813 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005815 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 if ((f=fopen(file,"r")) == NULL)
5818 return -1;
5819
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005820 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005821 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005822 char *end;
5823 char *args[MAX_LINE_ARGS + 1];
5824 char *line = thisline;
5825
Willy Tarreaubaaee002006-06-26 02:48:02 +02005826 linenum++;
5827
5828 end = line + strlen(line);
5829
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005830 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5831 /* Check if we reached the limit and the last char is not \n.
5832 * Watch out for the last line without the terminating '\n'!
5833 */
5834 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005835 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005836 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005837 }
5838
Willy Tarreaubaaee002006-06-26 02:48:02 +02005839 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005840 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841 line++;
5842
5843 arg = 0;
5844 args[arg] = line;
5845
5846 while (*line && arg < MAX_LINE_ARGS) {
5847 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5848 * C equivalent value. Other combinations left unchanged (eg: \1).
5849 */
5850 if (*line == '\\') {
5851 int skip = 0;
5852 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5853 *line = line[1];
5854 skip = 1;
5855 }
5856 else if (line[1] == 'r') {
5857 *line = '\r';
5858 skip = 1;
5859 }
5860 else if (line[1] == 'n') {
5861 *line = '\n';
5862 skip = 1;
5863 }
5864 else if (line[1] == 't') {
5865 *line = '\t';
5866 skip = 1;
5867 }
5868 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005869 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 unsigned char hex1, hex2;
5871 hex1 = toupper(line[2]) - '0';
5872 hex2 = toupper(line[3]) - '0';
5873 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5874 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5875 *line = (hex1<<4) + hex2;
5876 skip = 3;
5877 }
5878 else {
5879 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005880 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005881 }
5882 }
5883 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005884 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 end -= skip;
5886 }
5887 line++;
5888 }
5889 else if (*line == '#' || *line == '\n' || *line == '\r') {
5890 /* end of string, end of loop */
5891 *line = 0;
5892 break;
5893 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005894 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005895 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005896 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005897 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005898 line++;
5899 args[++arg] = line;
5900 }
5901 else {
5902 line++;
5903 }
5904 }
5905
5906 /* empty line */
5907 if (!**args)
5908 continue;
5909
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005910 if (*line) {
5911 /* we had to stop due to too many args.
5912 * Let's terminate the string, print the offending part then cut the
5913 * last arg.
5914 */
5915 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5916 line++;
5917 *line = '\0';
5918
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005919 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005920 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005921 err_code |= ERR_ALERT | ERR_FATAL;
5922 args[arg] = line;
5923 }
5924
Willy Tarreau540abe42007-05-02 20:50:16 +02005925 /* zero out remaining args and ensure that at least one entry
5926 * is zeroed out.
5927 */
5928 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005929 args[arg] = line;
5930 }
5931
Willy Tarreau3842f002009-06-14 11:39:52 +02005932 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005933 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005934 char *tmp;
5935
Willy Tarreau3842f002009-06-14 11:39:52 +02005936 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005937 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005938 for (arg=0; *args[arg+1]; arg++)
5939 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005940 *tmp = '\0'; // fix the next arg to \0
5941 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005942 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005943 else if (!strcmp(args[0], "default")) {
5944 kwm = KWM_DEF;
5945 for (arg=0; *args[arg+1]; arg++)
5946 args[arg] = args[arg+1]; // shift args after inversion
5947 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005948
William Lallemand0f99e342011-10-12 17:50:54 +02005949 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5950 strcmp(args[0], "log") != 0) {
5951 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005952 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005953 }
5954
Willy Tarreau977b8e42006-12-29 14:19:17 +01005955 if (!strcmp(args[0], "listen") ||
5956 !strcmp(args[0], "frontend") ||
5957 !strcmp(args[0], "backend") ||
5958 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005959 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005960 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005961 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005962 cursection = strdup(args[0]);
5963 }
5964 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005965 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005966 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005967 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005968 }
5969 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005970 confsect = CFG_USERLIST;
5971 free(cursection);
5972 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005973 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005974 else if (!strcmp(args[0], "peers")) {
5975 confsect = CFG_PEERS;
5976 free(cursection);
5977 cursection = strdup(args[0]);
5978 }
5979
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 /* else it's a section keyword */
5981
5982 switch (confsect) {
5983 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005984 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005985 break;
5986 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005987 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005989 case CFG_USERLIST:
5990 err_code |= cfg_parse_users(file, linenum, args, kwm);
5991 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005992 case CFG_PEERS:
5993 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5994 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005996 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005997 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005998 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005999
6000 if (err_code & ERR_ABORT)
6001 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006002 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006003 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006004 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006005 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006006 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006007}
6008
Willy Tarreaubb925012009-07-23 13:36:36 +02006009/*
6010 * Returns the error code, 0 if OK, or any combination of :
6011 * - ERR_ABORT: must abort ASAP
6012 * - ERR_FATAL: we can continue parsing but not start the service
6013 * - ERR_WARN: a warning has been emitted
6014 * - ERR_ALERT: an alert has been emitted
6015 * Only the two first ones can stop processing, the two others are just
6016 * indicators.
6017 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006018int check_config_validity()
6019{
6020 int cfgerr = 0;
6021 struct proxy *curproxy = NULL;
6022 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006023 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006024 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006025 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006026 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006027
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006028 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029 /*
6030 * Now, check for the integrity of all that we have collected.
6031 */
6032
6033 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006034 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006035
Willy Tarreau193b8c62012-11-22 00:17:38 +01006036 if (!global.tune.max_http_hdr)
6037 global.tune.max_http_hdr = MAX_HTTP_HDR;
6038
6039 if (!global.tune.cookie_len)
6040 global.tune.cookie_len = CAPTURE_LEN;
6041
6042 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6043
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006044 /* first, we will invert the proxy list order */
6045 curproxy = NULL;
6046 while (proxy) {
6047 struct proxy *next;
6048
6049 next = proxy->next;
6050 proxy->next = curproxy;
6051 curproxy = proxy;
6052 if (!next)
6053 break;
6054 proxy = next;
6055 }
6056
Willy Tarreaubaaee002006-06-26 02:48:02 +02006057 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006058 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006059 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006060 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006061 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006062 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006063 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006064 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006065
Willy Tarreau050536d2012-10-04 08:47:34 +02006066 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006067 /* proxy ID not set, use automatic numbering with first
6068 * spare entry starting with next_pxid.
6069 */
6070 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6071 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6072 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006073 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006074 next_pxid++;
6075
Willy Tarreau55ea7572007-06-17 19:56:27 +02006076
Willy Tarreaubaaee002006-06-26 02:48:02 +02006077 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006078 /* ensure we don't keep listeners uselessly bound */
6079 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006080 curproxy = curproxy->next;
6081 continue;
6082 }
6083
Willy Tarreau16a21472012-11-19 12:39:59 +01006084 /* number of processes this proxy is bound to */
6085 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6086
Willy Tarreauff01a212009-03-15 13:46:16 +01006087 switch (curproxy->mode) {
6088 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006089 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006090 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006091 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6092 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006093 cfgerr++;
6094 }
6095
6096 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006097 Warning("config : servers will be ignored for %s '%s'.\n",
6098 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006099 break;
6100
6101 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006102 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006103 break;
6104
6105 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006106 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006107 break;
6108 }
6109
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006110 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006111 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006112 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006113 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6114 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006115 cfgerr++;
6116 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006117#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006118 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006119 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6120 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006121 cfgerr++;
6122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006123#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006124 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006125 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6126 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006127 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006128 }
6129 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006130 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006131 /* If no LB algo is set in a backend, and we're not in
6132 * transparent mode, dispatch mode nor proxy mode, we
6133 * want to use balance roundrobin by default.
6134 */
6135 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6136 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006137 }
6138 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006139
Willy Tarreau1620ec32011-08-06 17:05:02 +02006140 if (curproxy->options & PR_O_DISPATCH)
6141 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6142 else if (curproxy->options & PR_O_HTTP_PROXY)
6143 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6144 else if (curproxy->options & PR_O_TRANSP)
6145 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006146
Willy Tarreau1620ec32011-08-06 17:05:02 +02006147 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6148 if (curproxy->options & PR_O_DISABLE404) {
6149 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6150 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6151 err_code |= ERR_WARN;
6152 curproxy->options &= ~PR_O_DISABLE404;
6153 }
6154 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6155 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6156 "send-state", proxy_type_str(curproxy), curproxy->id);
6157 err_code |= ERR_WARN;
6158 curproxy->options &= ~PR_O2_CHK_SNDST;
6159 }
Willy Tarreauef781042010-01-27 11:53:01 +01006160 }
6161
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006162 /* if a default backend was specified, let's find it */
6163 if (curproxy->defbe.name) {
6164 struct proxy *target;
6165
Alex Williams96532db2009-11-01 21:27:13 -05006166 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006167 if (!target) {
6168 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6169 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006170 cfgerr++;
6171 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006172 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6173 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006174 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006175 } else {
6176 free(curproxy->defbe.name);
6177 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006178 /* we force the backend to be present on at least all of
6179 * the frontend's processes.
6180 */
6181 target->bind_proc = curproxy->bind_proc ?
6182 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006183
6184 /* Emit a warning if this proxy also has some servers */
6185 if (curproxy->srv) {
6186 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6187 curproxy->id);
6188 err_code |= ERR_WARN;
6189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 }
6191 }
6192
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006193 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006194 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6195 /* map jump target for ACT_SETBE in req_rep chain */
6196 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006197 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006198 struct proxy *target;
6199
Willy Tarreaua496b602006-12-17 23:15:24 +01006200 if (exp->action != ACT_SETBE)
6201 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006202
Alex Williams96532db2009-11-01 21:27:13 -05006203 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006204 if (!target) {
6205 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6206 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006207 cfgerr++;
6208 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006209 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6210 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006211 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006212 } else {
6213 free((void *)exp->replace);
6214 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006215 /* we force the backend to be present on at least all of
6216 * the frontend's processes.
6217 */
6218 target->bind_proc = curproxy->bind_proc ?
6219 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006220 }
6221 }
6222 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006223
6224 /* find the target proxy for 'use_backend' rules */
6225 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006226 struct proxy *target;
6227
Alex Williams96532db2009-11-01 21:27:13 -05006228 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006229
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006230 if (!target) {
6231 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6232 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006233 cfgerr++;
6234 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006235 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6236 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006237 cfgerr++;
6238 } else {
6239 free((void *)rule->be.name);
6240 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006241 /* we force the backend to be present on at least all of
6242 * the frontend's processes.
6243 */
6244 target->bind_proc = curproxy->bind_proc ?
6245 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006246 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006247 }
6248
6249 /* find the target proxy for 'use_backend' rules */
6250 list_for_each_entry(srule, &curproxy->server_rules, list) {
6251 struct server *target = findserver(curproxy, srule->srv.name);
6252
6253 if (!target) {
6254 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6255 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6256 cfgerr++;
6257 continue;
6258 }
6259 free((void *)srule->srv.name);
6260 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006261 }
6262
Emeric Brunb982a3d2010-01-04 15:45:53 +01006263 /* find the target table for 'stick' rules */
6264 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6265 struct proxy *target;
6266
Emeric Brun1d33b292010-01-04 15:47:17 +01006267 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6268 if (mrule->flags & STK_IS_STORE)
6269 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6270
Emeric Brunb982a3d2010-01-04 15:45:53 +01006271 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006272 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006273 else
6274 target = curproxy;
6275
6276 if (!target) {
6277 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6278 curproxy->id, mrule->table.name);
6279 cfgerr++;
6280 }
6281 else if (target->table.size == 0) {
6282 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6283 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6284 cfgerr++;
6285 }
Willy Tarreau12785782012-04-27 21:37:17 +02006286 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6287 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006288 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6289 cfgerr++;
6290 }
6291 else {
6292 free((void *)mrule->table.name);
6293 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006294 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006295 }
6296 }
6297
6298 /* find the target table for 'store response' rules */
6299 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6300 struct proxy *target;
6301
Emeric Brun1d33b292010-01-04 15:47:17 +01006302 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6303
Emeric Brunb982a3d2010-01-04 15:45:53 +01006304 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006305 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006306 else
6307 target = curproxy;
6308
6309 if (!target) {
6310 Alert("Proxy '%s': unable to find store table '%s'.\n",
6311 curproxy->id, mrule->table.name);
6312 cfgerr++;
6313 }
6314 else if (target->table.size == 0) {
6315 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6316 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6317 cfgerr++;
6318 }
Willy Tarreau12785782012-04-27 21:37:17 +02006319 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6320 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006321 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6322 cfgerr++;
6323 }
6324 else {
6325 free((void *)mrule->table.name);
6326 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006327 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006328 }
6329 }
6330
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006331 /* find the target table for 'tcp-request' layer 4 rules */
6332 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6333 struct proxy *target;
6334
Willy Tarreau56123282010-08-06 19:06:56 +02006335 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006336 continue;
6337
6338 if (trule->act_prm.trk_ctr.table.n)
6339 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6340 else
6341 target = curproxy;
6342
6343 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006344 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6345 curproxy->id, trule->act_prm.trk_ctr.table.n,
6346 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006347 cfgerr++;
6348 }
6349 else if (target->table.size == 0) {
6350 Alert("Proxy '%s': table '%s' used but not configured.\n",
6351 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6352 cfgerr++;
6353 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006354 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6355 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6356 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6357 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6358 cfgerr++;
6359 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006360 else {
6361 free(trule->act_prm.trk_ctr.table.n);
6362 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006363 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006364 * to pass a list of counters to track and allocate them right here using
6365 * stktable_alloc_data_type().
6366 */
6367 }
6368 }
6369
Willy Tarreaud1f96522010-08-03 19:34:32 +02006370 /* find the target table for 'tcp-request' layer 6 rules */
6371 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6372 struct proxy *target;
6373
Willy Tarreau56123282010-08-06 19:06:56 +02006374 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006375 continue;
6376
6377 if (trule->act_prm.trk_ctr.table.n)
6378 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6379 else
6380 target = curproxy;
6381
6382 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006383 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6384 curproxy->id, trule->act_prm.trk_ctr.table.n,
6385 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006386 cfgerr++;
6387 }
6388 else if (target->table.size == 0) {
6389 Alert("Proxy '%s': table '%s' used but not configured.\n",
6390 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6391 cfgerr++;
6392 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006393 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6394 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6395 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6396 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6397 cfgerr++;
6398 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006399 else {
6400 free(trule->act_prm.trk_ctr.table.n);
6401 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006402 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006403 * to pass a list of counters to track and allocate them right here using
6404 * stktable_alloc_data_type().
6405 */
6406 }
6407 }
6408
Emeric Brun32da3c42010-09-23 18:39:19 +02006409 if (curproxy->table.peers.name) {
6410 struct peers *curpeers = peers;
6411
6412 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6413 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6414 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006415 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006416 break;
6417 }
6418 }
6419
6420 if (!curpeers) {
6421 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6422 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006423 free((void *)curproxy->table.peers.name);
6424 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006425 cfgerr++;
6426 }
6427 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006428 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6429 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006430 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006431 cfgerr++;
6432 }
6433 }
6434
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006435 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006436 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006437 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6438 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6439 "proxy", curproxy->id);
6440 cfgerr++;
6441 goto out_uri_auth_compat;
6442 }
6443
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006444 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006445 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006446 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006447 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006448
Willy Tarreau95fa4692010-02-01 13:05:50 +01006449 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6450 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006451
6452 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006453 uri_auth_compat_req[i++] = "realm";
6454 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6455 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006456
Willy Tarreau95fa4692010-02-01 13:05:50 +01006457 uri_auth_compat_req[i++] = "unless";
6458 uri_auth_compat_req[i++] = "{";
6459 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6460 uri_auth_compat_req[i++] = "}";
6461 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006462
Willy Tarreauff011f22011-01-06 17:51:27 +01006463 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6464 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006465 cfgerr++;
6466 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006467 }
6468
Willy Tarreauff011f22011-01-06 17:51:27 +01006469 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006470
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006471 if (curproxy->uri_auth->auth_realm) {
6472 free(curproxy->uri_auth->auth_realm);
6473 curproxy->uri_auth->auth_realm = NULL;
6474 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006475
6476 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006477 }
6478out_uri_auth_compat:
6479
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006480 /* compile the log format */
6481 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006482 if (curproxy->conf.logformat_string != default_http_log_format &&
6483 curproxy->conf.logformat_string != default_tcp_log_format &&
6484 curproxy->conf.logformat_string != clf_http_log_format)
6485 free(curproxy->conf.logformat_string);
6486 curproxy->conf.logformat_string = NULL;
6487 free(curproxy->conf.lfs_file);
6488 curproxy->conf.lfs_file = NULL;
6489 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006490 }
6491
Willy Tarreau62a61232013-04-12 18:13:46 +02006492 if (curproxy->conf.logformat_string) {
6493 curproxy->conf.args.ctx = ARGC_LOG;
6494 curproxy->conf.args.file = curproxy->conf.lfs_file;
6495 curproxy->conf.args.line = curproxy->conf.lfs_line;
6496 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006497 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006498 curproxy->conf.args.file = NULL;
6499 curproxy->conf.args.line = 0;
6500 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006501
Willy Tarreau62a61232013-04-12 18:13:46 +02006502 if (curproxy->conf.uniqueid_format_string) {
6503 curproxy->conf.args.ctx = ARGC_UIF;
6504 curproxy->conf.args.file = curproxy->conf.uif_file;
6505 curproxy->conf.args.line = curproxy->conf.uif_line;
6506 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006507 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006508 curproxy->conf.args.file = NULL;
6509 curproxy->conf.args.line = 0;
6510 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006511
6512 /* only now we can check if some args remain unresolved */
6513 cfgerr += smp_resolve_args(curproxy);
6514 if (!cfgerr)
6515 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006516
Willy Tarreau2738a142006-07-08 17:28:09 +02006517 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006518 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006519 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006520 (!curproxy->timeout.connect ||
6521 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006522 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006523 " | While not properly invalid, you will certainly encounter various problems\n"
6524 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006525 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006526 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006527 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006528 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006529
Willy Tarreau1fa31262007-12-03 00:36:16 +01006530 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6531 * We must still support older configurations, so let's find out whether those
6532 * parameters have been set or must be copied from contimeouts.
6533 */
6534 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006535 if (!curproxy->timeout.tarpit ||
6536 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006537 /* tarpit timeout not set. We search in the following order:
6538 * default.tarpit, curr.connect, default.connect.
6539 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006540 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006541 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006542 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006543 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006544 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006545 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006546 }
6547 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006548 (!curproxy->timeout.queue ||
6549 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006550 /* queue timeout not set. We search in the following order:
6551 * default.queue, curr.connect, default.connect.
6552 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006553 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006554 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006555 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006556 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006557 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006558 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006559 }
6560 }
6561
Willy Tarreau1620ec32011-08-06 17:05:02 +02006562 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006563 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6564 curproxy->check_req = (char *)malloc(curproxy->check_len);
6565 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006566 }
6567
Willy Tarreau193b8c62012-11-22 00:17:38 +01006568 /* ensure that cookie capture length is not too large */
6569 if (curproxy->capture_len >= global.tune.cookie_len) {
6570 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6571 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6572 err_code |= ERR_WARN;
6573 curproxy->capture_len = global.tune.cookie_len - 1;
6574 }
6575
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006576 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006577 if (curproxy->nb_req_cap) {
6578 if (curproxy->mode == PR_MODE_HTTP) {
6579 curproxy->req_cap_pool = create_pool("ptrcap",
6580 curproxy->nb_req_cap * sizeof(char *),
6581 MEM_F_SHARED);
6582 } else {
6583 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6584 proxy_type_str(curproxy), curproxy->id);
6585 err_code |= ERR_WARN;
6586 curproxy->to_log &= ~LW_REQHDR;
6587 curproxy->nb_req_cap = 0;
6588 }
6589 }
6590
6591 if (curproxy->nb_rsp_cap) {
6592 if (curproxy->mode == PR_MODE_HTTP) {
6593 curproxy->rsp_cap_pool = create_pool("ptrcap",
6594 curproxy->nb_rsp_cap * sizeof(char *),
6595 MEM_F_SHARED);
6596 } else {
6597 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6598 proxy_type_str(curproxy), curproxy->id);
6599 err_code |= ERR_WARN;
6600 curproxy->to_log &= ~LW_REQHDR;
6601 curproxy->nb_rsp_cap = 0;
6602 }
6603 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006604
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605 /* first, we will invert the servers list order */
6606 newsrv = NULL;
6607 while (curproxy->srv) {
6608 struct server *next;
6609
6610 next = curproxy->srv->next;
6611 curproxy->srv->next = newsrv;
6612 newsrv = curproxy->srv;
6613 if (!next)
6614 break;
6615 curproxy->srv = next;
6616 }
6617
Willy Tarreaudd701652010-05-25 23:03:02 +02006618 /* assign automatic UIDs to servers which don't have one yet */
6619 next_id = 1;
6620 newsrv = curproxy->srv;
6621 while (newsrv != NULL) {
6622 if (!newsrv->puid) {
6623 /* server ID not set, use automatic numbering with first
6624 * spare entry starting with next_svid.
6625 */
6626 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6627 newsrv->conf.id.key = newsrv->puid = next_id;
6628 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6629 }
6630 next_id++;
6631 newsrv = newsrv->next;
6632 }
6633
Willy Tarreau20697042007-11-15 23:26:18 +01006634 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006635 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006636
Willy Tarreau62c3be22012-01-20 13:12:32 +01006637 /*
6638 * If this server supports a maxconn parameter, it needs a dedicated
6639 * tasks to fill the emptied slots when a connection leaves.
6640 * Also, resolve deferred tracking dependency if needed.
6641 */
6642 newsrv = curproxy->srv;
6643 while (newsrv != NULL) {
6644 if (newsrv->minconn > newsrv->maxconn) {
6645 /* Only 'minconn' was specified, or it was higher than or equal
6646 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6647 * this will avoid further useless expensive computations.
6648 */
6649 newsrv->maxconn = newsrv->minconn;
6650 } else if (newsrv->maxconn && !newsrv->minconn) {
6651 /* minconn was not specified, so we set it to maxconn */
6652 newsrv->minconn = newsrv->maxconn;
6653 }
6654
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006655#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006656 if (newsrv->use_ssl || newsrv->check.use_ssl)
6657 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006658#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006659
Willy Tarreau62c3be22012-01-20 13:12:32 +01006660 if (newsrv->trackit) {
6661 struct proxy *px;
6662 struct server *srv;
6663 char *pname, *sname;
6664
6665 pname = newsrv->trackit;
6666 sname = strrchr(pname, '/');
6667
6668 if (sname)
6669 *sname++ = '\0';
6670 else {
6671 sname = pname;
6672 pname = NULL;
6673 }
6674
6675 if (pname) {
6676 px = findproxy(pname, PR_CAP_BE);
6677 if (!px) {
6678 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6679 proxy_type_str(curproxy), curproxy->id,
6680 newsrv->id, pname);
6681 cfgerr++;
6682 goto next_srv;
6683 }
6684 } else
6685 px = curproxy;
6686
6687 srv = findserver(px, sname);
6688 if (!srv) {
6689 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6690 proxy_type_str(curproxy), curproxy->id,
6691 newsrv->id, sname);
6692 cfgerr++;
6693 goto next_srv;
6694 }
6695
6696 if (!(srv->state & SRV_CHECKED)) {
6697 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6698 "tracking as it does not have checks enabled.\n",
6699 proxy_type_str(curproxy), curproxy->id,
6700 newsrv->id, px->id, srv->id);
6701 cfgerr++;
6702 goto next_srv;
6703 }
6704
6705 if (curproxy != px &&
6706 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6707 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6708 "tracking: disable-on-404 option inconsistency.\n",
6709 proxy_type_str(curproxy), curproxy->id,
6710 newsrv->id, px->id, srv->id);
6711 cfgerr++;
6712 goto next_srv;
6713 }
6714
6715 /* if the other server is forced disabled, we have to do the same here */
6716 if (srv->state & SRV_MAINTAIN) {
6717 newsrv->state |= SRV_MAINTAIN;
6718 newsrv->state &= ~SRV_RUNNING;
6719 newsrv->health = 0;
6720 }
6721
6722 newsrv->track = srv;
6723 newsrv->tracknext = srv->tracknext;
6724 srv->tracknext = newsrv;
6725
6726 free(newsrv->trackit);
6727 newsrv->trackit = NULL;
6728 }
6729 next_srv:
6730 newsrv = newsrv->next;
6731 }
6732
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006733 /* We have to initialize the server lookup mechanism depending
6734 * on what LB algorithm was choosen.
6735 */
6736
6737 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6738 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6739 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006740 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6741 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6742 init_server_map(curproxy);
6743 } else {
6744 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6745 fwrr_init_server_groups(curproxy);
6746 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006747 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006748
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006749 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006750 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6751 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6752 fwlc_init_server_tree(curproxy);
6753 } else {
6754 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6755 fas_init_server_tree(curproxy);
6756 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006757 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006758
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006759 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006760 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6761 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6762 chash_init_server_tree(curproxy);
6763 } else {
6764 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6765 init_server_map(curproxy);
6766 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006767 break;
6768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006769
6770 if (curproxy->options & PR_O_LOGASAP)
6771 curproxy->to_log &= ~LW_BYTES;
6772
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006773 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006774 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006775 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6776 proxy_type_str(curproxy), curproxy->id);
6777 err_code |= ERR_WARN;
6778 }
6779
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006780 if (curproxy->mode != PR_MODE_HTTP) {
6781 int optnum;
6782
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006783 if (curproxy->uri_auth) {
6784 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6785 proxy_type_str(curproxy), curproxy->id);
6786 err_code |= ERR_WARN;
6787 curproxy->uri_auth = NULL;
6788 }
6789
Willy Tarreau87cf5142011-08-19 22:57:24 +02006790 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006791 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6792 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6793 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006794 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006795 }
6796
6797 if (curproxy->options & PR_O_ORGTO) {
6798 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6799 "originalto", proxy_type_str(curproxy), curproxy->id);
6800 err_code |= ERR_WARN;
6801 curproxy->options &= ~PR_O_ORGTO;
6802 }
6803
6804 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6805 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6806 (curproxy->cap & cfg_opts[optnum].cap) &&
6807 (curproxy->options & cfg_opts[optnum].val)) {
6808 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6809 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6810 err_code |= ERR_WARN;
6811 curproxy->options &= ~cfg_opts[optnum].val;
6812 }
6813 }
6814
6815 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6816 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6817 (curproxy->cap & cfg_opts2[optnum].cap) &&
6818 (curproxy->options2 & cfg_opts2[optnum].val)) {
6819 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6820 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6821 err_code |= ERR_WARN;
6822 curproxy->options2 &= ~cfg_opts2[optnum].val;
6823 }
6824 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006825
Willy Tarreauefa5f512010-03-30 20:13:29 +02006826#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006827 if (curproxy->conn_src.bind_hdr_occ) {
6828 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006829 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006830 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006831 err_code |= ERR_WARN;
6832 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006833#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006834 }
6835
Willy Tarreaubaaee002006-06-26 02:48:02 +02006836 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006837 * ensure that we're not cross-dressing a TCP server into HTTP.
6838 */
6839 newsrv = curproxy->srv;
6840 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006841 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006842 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6843 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006844 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006845 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006846
Willy Tarreau0cec3312011-10-31 13:49:26 +01006847 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6848 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6849 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6850 err_code |= ERR_WARN;
6851 }
6852
Willy Tarreauefa5f512010-03-30 20:13:29 +02006853#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006854 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6855 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006856 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 +01006857 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006858 err_code |= ERR_WARN;
6859 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006860#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006861 newsrv = newsrv->next;
6862 }
6863
Willy Tarreauc1a21672009-08-16 22:37:44 +02006864 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006865 if (!curproxy->accept)
6866 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006867
Willy Tarreauc1a21672009-08-16 22:37:44 +02006868 if (curproxy->tcp_req.inspect_delay ||
6869 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006870 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006871
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006872 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006873 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006874 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006875 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006876
6877 /* both TCP and HTTP must check switching rules */
6878 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6879 }
6880
6881 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006882 if (curproxy->tcp_req.inspect_delay ||
6883 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6884 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6885
Emeric Brun97679e72010-09-23 17:56:44 +02006886 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6887 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6888
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006889 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006890 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006891 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006892 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006893
6894 /* If the backend does requires RDP cookie persistence, we have to
6895 * enable the corresponding analyser.
6896 */
6897 if (curproxy->options2 & PR_O2_RDPC_PRST)
6898 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6899 }
6900
Emeric Brunc52962f2012-11-15 18:28:02 +01006901#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006902 /* Configure SSL for each bind line.
6903 * Note: if configuration fails at some point, the ->ctx member
6904 * remains NULL so that listeners can later detach.
6905 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006906 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006907 if (!bind_conf->is_ssl) {
6908 if (bind_conf->default_ctx) {
6909 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6910 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6911 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006912 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006913 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006914 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006915 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006916 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006917 cfgerr++;
6918 continue;
6919 }
6920
Emeric Brun4b3091e2012-09-24 15:48:52 +02006921 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006922 Alert("Unable to allocate SSL session cache.\n");
6923 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006924 continue;
6925 }
6926
Emeric Brunfc0421f2012-09-07 17:30:07 +02006927 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006928 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006929 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006930#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006931
Willy Tarreaue6b98942007-10-29 01:09:36 +01006932 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006933 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006934 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006935 if (!listener->luid) {
6936 /* listener ID not set, use automatic numbering with first
6937 * spare entry starting with next_luid.
6938 */
6939 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6940 listener->conf.id.key = listener->luid = next_id;
6941 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006942 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006943 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006944
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006945 /* enable separate counters */
6946 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6947 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006948 if (!listener->name)
6949 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006950 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006951
Willy Tarreaue6b98942007-10-29 01:09:36 +01006952 if (curproxy->options & PR_O_TCP_NOLING)
6953 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006954 if (!listener->maxconn)
6955 listener->maxconn = curproxy->maxconn;
6956 if (!listener->backlog)
6957 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006958 if (!listener->maxaccept)
6959 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6960
6961 /* we want to have an optimal behaviour on single process mode to
6962 * maximize the work at once, but in multi-process we want to keep
6963 * some fairness between processes, so we target half of the max
6964 * number of events to be balanced over all the processes the proxy
6965 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6966 * used to disable the limit.
6967 */
6968 if (listener->maxaccept > 0) {
6969 if (nbproc > 1)
6970 listener->maxaccept = (listener->maxaccept + 1) / 2;
6971 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6972 }
6973
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006974 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006975 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006976 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006977 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006978
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006979 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6980 listener->options |= LI_O_TCP_RULES;
6981
Willy Tarreaude3041d2010-05-31 10:56:17 +02006982 if (curproxy->mon_mask.s_addr)
6983 listener->options |= LI_O_CHK_MONNET;
6984
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006985 /* smart accept mode is automatic in HTTP mode */
6986 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006987 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006988 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6989 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006990 }
6991
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006992 /* Release unused SSL configs */
6993 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6994 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006995 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006996#ifdef USE_OPENSSL
6997 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006998 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006999 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007000 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007001 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007002#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007003 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007004
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007005 /* Check multi-process mode compatibility for the current proxy */
7006 if (global.nbproc > 1) {
7007 int nbproc = 0;
7008 if (curproxy->bind_proc) {
7009 int proc;
7010 for (proc = 0; proc < global.nbproc; proc++) {
7011 if (curproxy->bind_proc & (1 << proc)) {
7012 nbproc++;
7013 }
7014 }
7015 } else {
7016 nbproc = global.nbproc;
7017 }
7018 if (curproxy->table.peers.name) {
7019 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7020 curproxy->id);
7021 cfgerr++;
7022 }
7023 if (nbproc > 1) {
7024 if (curproxy->uri_auth) {
7025 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7026 curproxy->id);
7027 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7028 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7029 curproxy->id);
7030 }
7031 }
7032 if (curproxy->appsession_name) {
7033 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7034 curproxy->id);
7035 }
7036 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7037 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7038 curproxy->id);
7039 }
7040 }
7041 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007042
7043 /* create the task associated with the proxy */
7044 curproxy->task = task_new();
7045 if (curproxy->task) {
7046 curproxy->task->context = curproxy;
7047 curproxy->task->process = manage_proxy;
7048 /* no need to queue, it will be done automatically if some
7049 * listener gets limited.
7050 */
7051 curproxy->task->expire = TICK_ETERNITY;
7052 } else {
7053 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7054 curproxy->id);
7055 cfgerr++;
7056 }
7057
Willy Tarreaubaaee002006-06-26 02:48:02 +02007058 curproxy = curproxy->next;
7059 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007060
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007061 /* Check multi-process mode compatibility */
7062 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007063 if (global.stats_fe && !global.stats_fe->bind_proc) {
7064 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 +01007065 }
7066 }
7067
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007068 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7069 struct auth_users *curuser;
7070 int g;
7071
7072 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7073 unsigned int group_mask = 0;
7074 char *group = NULL;
7075
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007076 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007077 continue;
7078
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007079 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007080
7081 for (g = 0; g < curuserlist->grpcnt; g++)
7082 if (!strcmp(curuserlist->groups[g], group))
7083 break;
7084
7085 if (g == curuserlist->grpcnt) {
7086 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7087 curuserlist->name, group, curuser->user);
7088 err_code |= ERR_ALERT | ERR_FATAL;
7089 goto out;
7090 }
7091
7092 group_mask |= (1 << g);
7093 }
7094
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007095 free(curuser->u.groups);
7096 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007097 }
7098
7099 for (g = 0; g < curuserlist->grpcnt; g++) {
7100 char *user = NULL;
7101
7102 if (!curuserlist->groupusers[g])
7103 continue;
7104
7105 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7106 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7107 if (!strcmp(curuser->user, user))
7108 break;
7109
7110 if (!curuser) {
7111 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7112 curuserlist->name, user, curuserlist->groups[g]);
7113 err_code |= ERR_ALERT | ERR_FATAL;
7114 goto out;
7115 }
7116
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007117 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007118 }
7119
7120 free(curuserlist->groupusers[g]);
7121 }
7122
7123 free(curuserlist->groupusers);
7124
7125#ifdef DEBUG_AUTH
7126 for (g = 0; g < curuserlist->grpcnt; g++) {
7127 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7128
7129 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007130 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007131 fprintf(stderr, " %s", curuser->user);
7132 }
7133
7134 fprintf(stderr, "\n");
7135 }
7136#endif
7137
Willy Tarreaufbb78422011-06-05 15:38:35 +02007138 }
7139
7140 /* automatically compute fullconn if not set. We must not do it in the
7141 * loop above because cross-references are not yet fully resolved.
7142 */
7143 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7144 /* If <fullconn> is not set, let's set it to 10% of the sum of
7145 * the possible incoming frontend's maxconns.
7146 */
7147 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7148 struct proxy *fe;
7149 int total = 0;
7150
7151 /* sum up the number of maxconns of frontends which
7152 * reference this backend at least once or which are
7153 * the same one ('listen').
7154 */
7155 for (fe = proxy; fe; fe = fe->next) {
7156 struct switching_rule *rule;
7157 struct hdr_exp *exp;
7158 int found = 0;
7159
7160 if (!(fe->cap & PR_CAP_FE))
7161 continue;
7162
7163 if (fe == curproxy) /* we're on a "listen" instance */
7164 found = 1;
7165
7166 if (fe->defbe.be == curproxy) /* "default_backend" */
7167 found = 1;
7168
7169 /* check if a "use_backend" rule matches */
7170 if (!found) {
7171 list_for_each_entry(rule, &fe->switching_rules, list) {
7172 if (rule->be.backend == curproxy) {
7173 found = 1;
7174 break;
7175 }
7176 }
7177 }
7178
7179 /* check if a "reqsetbe" rule matches */
7180 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7181 if (exp->action == ACT_SETBE &&
7182 (struct proxy *)exp->replace == curproxy) {
7183 found = 1;
7184 break;
7185 }
7186 }
7187
7188 /* now we've checked all possible ways to reference a backend
7189 * from a frontend.
7190 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007191 if (!found)
7192 continue;
7193 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007194 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007195 /* we have the sum of the maxconns in <total>. We only
7196 * keep 10% of that sum to set the default fullconn, with
7197 * a hard minimum of 1 (to avoid a divide by zero).
7198 */
7199 curproxy->fullconn = (total + 9) / 10;
7200 if (!curproxy->fullconn)
7201 curproxy->fullconn = 1;
7202 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007203 }
7204
Willy Tarreau056f5682010-06-06 15:51:11 +02007205 /* initialize stick-tables on backend capable proxies. This must not
7206 * be done earlier because the data size may be discovered while parsing
7207 * other proxies.
7208 */
7209 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007210 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007211
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007212 /*
7213 * Recount currently required checks.
7214 */
7215
7216 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7217 int optnum;
7218
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007219 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7220 if (curproxy->options & cfg_opts[optnum].val)
7221 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007222
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007223 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7224 if (curproxy->options2 & cfg_opts2[optnum].val)
7225 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007226 }
7227
Willy Tarreau122541c2011-09-07 21:24:49 +02007228 if (peers) {
7229 struct peers *curpeers = peers, **last;
7230 struct peer *p, *pb;
7231
7232 /* Remove all peers sections which don't have a valid listener.
7233 * This can happen when a peers section is never referenced and
7234 * does not contain a local peer.
7235 */
7236 last = &peers;
7237 while (*last) {
7238 curpeers = *last;
7239 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007240 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007241 last = &curpeers->next;
7242 continue;
7243 }
7244
7245 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7246 curpeers->id, localpeer);
7247
7248 p = curpeers->remote;
7249 while (p) {
7250 pb = p->next;
7251 free(p->id);
7252 free(p);
7253 p = pb;
7254 }
7255
7256 /* Destroy and unlink this curpeers section.
7257 * Note: curpeers is backed up into *last.
7258 */
7259 free(curpeers->id);
7260 curpeers = curpeers->next;
7261 free(*last);
7262 *last = curpeers;
7263 }
7264 }
7265
Willy Tarreau34eb6712011-10-24 18:15:04 +02007266 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007267 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007268 MEM_F_SHARED);
7269
Willy Tarreaubb925012009-07-23 13:36:36 +02007270 if (cfgerr > 0)
7271 err_code |= ERR_ALERT | ERR_FATAL;
7272 out:
7273 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007274}
7275
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007276/*
7277 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7278 * parsing sessions.
7279 */
7280void cfg_register_keywords(struct cfg_kw_list *kwl)
7281{
7282 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7283}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007284
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007285/*
7286 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7287 */
7288void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7289{
7290 LIST_DEL(&kwl->list);
7291 LIST_INIT(&kwl->list);
7292}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007293
7294/*
7295 * Local variables:
7296 * c-indent-level: 8
7297 * c-basic-offset: 8
7298 * End:
7299 */