blob: 276766bff9eb848dd8c75bf33daae12efe6f6ba7 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100209 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100210 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
212 str = next;
213 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100214 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 *next++ = 0;
216 }
217
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100218 ss2 = str2sa_range(str, &port, &end, err,
219 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
220 if (!ss2)
221 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100223 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100224 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100229 if (!port || !end) {
230 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
231 goto fail;
232 }
233
Emeric Bruned760922010-10-22 17:59:25 +0200234 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200235 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200236 goto fail;
237 }
238
239 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200240 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 else if (ss2->ss_family == AF_UNSPEC) {
245 socklen_t addr_len;
246
247 /* We want to attach to an already bound fd whose number
248 * is in the addr part of ss2 when cast to sockaddr_in.
249 * Note that by definition there is a single listener.
250 * We still have to determine the address family to
251 * register the correct protocol.
252 */
253 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
254 addr_len = sizeof(*ss2);
255 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
256 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
257 goto fail;
258 }
259
260 port = end = get_host_port(ss2);
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100263 /* OK the address looks correct */
264 ss = *ss2;
265
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100268 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200269 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
270 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
271 l->frontend = curproxy;
272 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273
Willy Tarreau40aa0702013-03-10 23:51:38 +0100274 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200276 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100277 l->state = LI_INIT;
278
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100279 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100281 tcpv4_add_listener(l);
282 }
Emeric Bruned760922010-10-22 17:59:25 +0200283 else if (ss.ss_family == AF_INET6) {
284 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
285 tcpv6_add_listener(l);
286 }
287 else {
Emeric Bruned760922010-10-22 17:59:25 +0200288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100417/* Report it if a request ACL condition uses some keywords that are incompatible
418 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
419 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
420 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100421 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100422static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200425 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100428 return 0;
429
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100430 acl = acl_cond_conflicts(cond, where);
431 if (acl) {
432 if (acl->name && *acl->name)
433 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
434 file, line, acl->name, sample_ckp_names(where));
435 else
436 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200437 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100438 return ERR_WARN;
439 }
440 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100441 return 0;
442
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 if (acl->name && *acl->name)
444 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446 else
447 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200448 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100449 return ERR_WARN;
450}
451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200471 else if (!strcmp(args[0], "ca-base")) {
472#ifdef USE_OPENSSL
473 if (global.ca_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.ca_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
490 else if (!strcmp(args[0], "crt-base")) {
491#ifdef USE_OPENSSL
492 if (global.crt_base != NULL) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.crt_base = strdup(args[1]);
503#else
504 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507#endif
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "daemon")) {
510 global.mode |= MODE_DAEMON;
511 }
512 else if (!strcmp(args[0], "debug")) {
513 global.mode |= MODE_DEBUG;
514 }
515 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200518 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100524 else if (!strcmp(args[0], "nosplice")) {
525 global.tune.options &= ~GTUNE_USE_SPLICE;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "quiet")) {
528 global.mode |= MODE_QUIET;
529 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200530 else if (!strcmp(args[0], "tune.maxpollevents")) {
531 if (global.tune.maxpollevents != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200540 }
541 global.tune.maxpollevents = atol(args[1]);
542 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100543 else if (!strcmp(args[0], "tune.maxaccept")) {
544 if (global.tune.maxaccept != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100553 }
554 global.tune.maxaccept = atol(args[1]);
555 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200556 else if (!strcmp(args[0], "tune.chksize")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.chksize = atol(args[1]);
563 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200564#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100565 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.sslcachesize = atol(args[1]);
572 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100573 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
574 unsigned int ssllifetime;
575 const char *res;
576
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582
583 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
584 if (res) {
585 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
586 file, linenum, *res, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590
591 global.tune.ssllifetime = ssllifetime;
592 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100593 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.ssl_max_record = atol(args[1]);
600 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200602 else if (!strcmp(args[0], "tune.bufsize")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.bufsize = atol(args[1]);
609 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
610 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100611 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200612 }
613 else if (!strcmp(args[0], "tune.maxrewrite")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.maxrewrite = atol(args[1]);
620 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
621 global.tune.maxrewrite = global.tune.bufsize / 2;
622 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100623 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
624 if (global.tune.client_rcvbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_rcvbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
637 if (global.tune.server_rcvbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_rcvbuf = atol(args[1]);
648 }
649 else if (!strcmp(args[0], "tune.sndbuf.client")) {
650 if (global.tune.client_sndbuf != 0) {
651 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT;
653 goto out;
654 }
655 if (*(args[1]) == 0) {
656 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT | ERR_FATAL;
658 goto out;
659 }
660 global.tune.client_sndbuf = atol(args[1]);
661 }
662 else if (!strcmp(args[0], "tune.sndbuf.server")) {
663 if (global.tune.server_sndbuf != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT;
666 goto out;
667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673 global.tune.server_sndbuf = atol(args[1]);
674 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200675 else if (!strcmp(args[0], "tune.pipesize")) {
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.tune.pipesize = atol(args[1]);
682 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100683 else if (!strcmp(args[0], "tune.http.cookielen")) {
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689 global.tune.cookie_len = atol(args[1]) + 1;
690 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200691 else if (!strcmp(args[0], "tune.http.maxhdr")) {
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 global.tune.max_http_hdr = atol(args[1]);
698 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100699 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
700#ifdef USE_ZLIB
701 if (*args[1]) {
702 global.tune.zlibmemlevel = atoi(args[1]);
703 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
704 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
705 file, linenum, args[0]);
706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
708 }
709 } else {
710 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715#else
716 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719#endif
720 }
721 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
722#ifdef USE_ZLIB
723 if (*args[1]) {
724 global.tune.zlibwindowsize = atoi(args[1]);
725 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
726 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
727 file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 } else {
732 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
733 file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737#else
738 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741#endif
742 }
William Lallemandf3747832012-11-09 12:33:10 +0100743 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
744 if (*args[1]) {
745 global.tune.comp_maxlevel = atoi(args[1]);
746 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
747 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
748 file, linenum, args[0]);
749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
751 }
752 } else {
753 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
754 file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 else if (!strcmp(args[0], "uid")) {
760 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200761 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200762 err_code |= ERR_ALERT;
763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770 global.uid = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "gid")) {
773 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200774 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT;
776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
783 global.gid = atol(args[1]);
784 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 /* user/group name handling */
786 else if (!strcmp(args[0], "user")) {
787 struct passwd *ha_user;
788 if (global.uid != 0) {
789 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200792 }
793 errno = 0;
794 ha_user = getpwnam(args[1]);
795 if (ha_user != NULL) {
796 global.uid = (int)ha_user->pw_uid;
797 }
798 else {
799 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200801 }
802 }
803 else if (!strcmp(args[0], "group")) {
804 struct group *ha_group;
805 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200806 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT;
808 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200809 }
810 errno = 0;
811 ha_group = getgrnam(args[1]);
812 if (ha_group != NULL) {
813 global.gid = (int)ha_group->gr_gid;
814 }
815 else {
816 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200818 }
819 }
820 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 global.nbproc = atol(args[1]);
828 }
829 else if (!strcmp(args[0], "maxconn")) {
830 if (global.maxconn != 0) {
831 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT;
833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840 global.maxconn = atol(args[1]);
841#ifdef SYSTEM_MAXCONN
842 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
843 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
844 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847#endif /* SYSTEM_MAXCONN */
848 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200849 else if (!strcmp(args[0], "maxsslconn")) {
850#ifdef USE_OPENSSL
851 if (*(args[1]) == 0) {
852 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
853 err_code |= ERR_ALERT | ERR_FATAL;
854 goto out;
855 }
856 global.maxsslconn = atol(args[1]);
857#else
Emeric Brun0914df82012-10-02 18:45:42 +0200858 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200861#endif
862 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200863 else if (!strcmp(args[0], "maxconnrate")) {
864 if (global.cps_lim != 0) {
865 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT;
867 goto out;
868 }
869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.cps_lim = atol(args[1]);
875 }
William Lallemandd85f9172012-11-09 17:05:39 +0100876 else if (!strcmp(args[0], "maxcomprate")) {
877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 global.comp_rate_lim = atoi(args[1]) * 1024;
883 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100884 else if (!strcmp(args[0], "maxpipes")) {
885 if (global.maxpipes != 0) {
886 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_ALERT;
888 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100889 }
890 if (*(args[1]) == 0) {
891 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100894 }
895 global.maxpipes = atol(args[1]);
896 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 else if (!strcmp(args[0], "maxzlibmem")) {
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
William Lallemande3a7d992012-11-20 11:25:20 +0100903 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100904 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100905 else if (!strcmp(args[0], "maxcompcpuusage")) {
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100912 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100913 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917}
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 else if (!strcmp(args[0], "ulimit-n")) {
920 if (global.rlimit_nofile != 0) {
921 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
925 if (*(args[1]) == 0) {
926 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930 global.rlimit_nofile = atol(args[1]);
931 }
932 else if (!strcmp(args[0], "chroot")) {
933 if (global.chroot != NULL) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 global.chroot = strdup(args[1]);
944 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200945 else if (!strcmp(args[0], "description")) {
946 int i, len=0;
947 char *d;
948
949 if (!*args[1]) {
950 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
951 file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 for(i=1; *args[i]; i++)
957 len += strlen(args[i])+1;
958
959 if (global.desc)
960 free(global.desc);
961
962 global.desc = d = (char *)calloc(1, len);
963
964 d += sprintf(d, "%s", args[1]);
965 for(i=2; *args[i]; i++)
966 d += sprintf(d, " %s", args[i]);
967 }
968 else if (!strcmp(args[0], "node")) {
969 int i;
970 char c;
971
972 for (i=0; args[1][i]; i++) {
973 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100974 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
975 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200976 break;
977 }
978
979 if (!i || args[1][i]) {
980 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
981 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
982 file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
986
987 if (global.node)
988 free(global.node);
989
990 global.node = strdup(args[1]);
991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "pidfile")) {
993 if (global.pidfile != NULL) {
994 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 }
1003 global.pidfile = strdup(args[1]);
1004 }
Emeric Bruned760922010-10-22 17:59:25 +02001005 else if (!strcmp(args[0], "unix-bind")) {
1006 int cur_arg = 1;
1007 while (*(args[cur_arg])) {
1008 if (!strcmp(args[cur_arg], "prefix")) {
1009 if (global.unix_bind.prefix != NULL) {
1010 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT;
1012 cur_arg += 2;
1013 continue;
1014 }
1015
1016 if (*(args[cur_arg+1]) == 0) {
1017 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020 }
1021 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "mode")) {
1027
1028 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "uid")) {
1034
1035 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "gid")) {
1041
1042 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1043 cur_arg += 2;
1044 continue;
1045 }
1046
1047 if (!strcmp(args[cur_arg], "user")) {
1048 struct passwd *user;
1049
1050 user = getpwnam(args[cur_arg + 1]);
1051 if (!user) {
1052 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1053 file, linenum, args[0], args[cur_arg + 1 ]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057
1058 global.unix_bind.ux.uid = user->pw_uid;
1059 cur_arg += 2;
1060 continue;
1061 }
1062
1063 if (!strcmp(args[cur_arg], "group")) {
1064 struct group *group;
1065
1066 group = getgrnam(args[cur_arg + 1]);
1067 if (!group) {
1068 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1069 file, linenum, args[0], args[cur_arg + 1 ]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073
1074 global.unix_bind.ux.gid = group->gr_gid;
1075 cur_arg += 2;
1076 continue;
1077 }
1078
Willy Tarreaub48f9582011-09-05 01:17:06 +02001079 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001080 file, linenum, args[0]);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084 }
William Lallemand0f99e342011-10-12 17:50:54 +02001085 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1086 /* delete previous herited or defined syslog servers */
1087 struct logsrv *back;
1088 struct logsrv *tmp;
1089
1090 if (*(args[1]) != 0) {
1091 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095
1096 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1097 LIST_DEL(&tmp->list);
1098 free(tmp);
1099 }
1100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001102 struct sockaddr_storage *sk;
1103 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001104 struct logsrv *logsrv;
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 if (*(args[1]) == 0 || *(args[2]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
William Lallemand0f99e342011-10-12 17:50:54 +02001111
1112 logsrv = calloc(1, sizeof(struct logsrv));
1113
1114 logsrv->facility = get_log_facility(args[2]);
1115 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120
William Lallemand0f99e342011-10-12 17:50:54 +02001121 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001123 logsrv->level = get_log_level(args[3]);
1124 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001127 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 }
1130
William Lallemand0f99e342011-10-12 17:50:54 +02001131 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001132 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001133 logsrv->minlvl = get_log_level(args[4]);
1134 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001135 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001137 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001138 }
1139 }
1140
Willy Tarreau902636f2013-03-10 19:44:48 +01001141 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001142 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001143 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001144 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001145 free(logsrv);
1146 goto out;
1147 }
1148 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001149
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001150 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001151 if (port1 != port2) {
1152 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1153 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001154 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001155 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001156 goto out;
1157 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001158
William Lallemand0f99e342011-10-12 17:50:54 +02001159 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001160 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001161 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163
William Lallemand0f99e342011-10-12 17:50:54 +02001164 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001165 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001166 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1167 char *name;
1168 int len;
1169
1170 if (global.log_send_hostname != NULL) {
1171 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT;
1173 goto out;
1174 }
1175
1176 if (*(args[1]))
1177 name = args[1];
1178 else
1179 name = hostname;
1180
1181 len = strlen(name);
1182
1183 /* We'll add a space after the name to respect the log format */
1184 free(global.log_send_hostname);
1185 global.log_send_hostname = malloc(len + 2);
1186 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1187 }
Kevinm48936af2010-12-22 16:08:21 +00001188 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
1193 }
1194 free(global.log_tag);
1195 global.log_tag = strdup(args[1]);
1196 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001197 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1198 if (global.spread_checks != 0) {
1199 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001207 }
1208 global.spread_checks = atol(args[1]);
1209 if (global.spread_checks < 0 || global.spread_checks > 50) {
1210 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001211 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001214 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1215#ifdef USE_CPU_AFFINITY
1216 int cur_arg, i;
1217 unsigned int proc = 0;
1218 unsigned long cpus = 0;
1219
1220 if (strcmp(args[1], "all") == 0)
1221 proc = 0xFFFFFFFF;
1222 else if (strcmp(args[1], "odd") == 0)
1223 proc = 0x55555555;
1224 else if (strcmp(args[1], "even") == 0)
1225 proc = 0xAAAAAAAA;
1226 else {
1227 proc = atoi(args[1]);
1228 if (proc >= 1 && proc <= 32)
1229 proc = 1 << (proc - 1);
1230 }
1231
1232 if (!proc || !*args[2]) {
1233 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1234 file, linenum, args[0]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 cur_arg = 2;
1240 while (*args[cur_arg]) {
1241 unsigned int low, high;
1242
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001243 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001244 char *dash = strchr(args[cur_arg], '-');
1245
1246 low = high = str2uic(args[cur_arg]);
1247 if (dash)
1248 high = str2uic(dash + 1);
1249
1250 if (high < low) {
1251 unsigned int swap = low;
1252 low = high;
1253 high = swap;
1254 }
1255
1256 if (low < 0 || high >= sizeof(long) * 8) {
1257 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1258 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 while (low <= high)
1264 cpus |= 1UL << low++;
1265 }
1266 else {
1267 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1268 file, linenum, args[0], args[cur_arg]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 cur_arg++;
1273 }
1274 for (i = 0; i < 32; i++)
1275 if (proc & (1 << i))
1276 global.cpu_map[i] = cpus;
1277#else
1278 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281#endif
1282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001284 struct cfg_kw_list *kwl;
1285 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001286 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001287
1288 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1289 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1290 if (kwl->kw[index].section != CFG_GLOBAL)
1291 continue;
1292 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001293 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001294 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001295 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001297 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001298 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001299 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_WARN;
1301 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001302 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001304 }
1305 }
1306 }
1307
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001311
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001313 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315}
1316
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001317void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001319 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 defproxy.mode = PR_MODE_TCP;
1321 defproxy.state = PR_STNEW;
1322 defproxy.maxconn = cfg_maxpconn;
1323 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001324
1325 defproxy.defsrv.inter = DEF_CHKINTR;
1326 defproxy.defsrv.fastinter = 0;
1327 defproxy.defsrv.downinter = 0;
1328 defproxy.defsrv.rise = DEF_RISETIME;
1329 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001330 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001331 defproxy.defsrv.maxqueue = 0;
1332 defproxy.defsrv.minconn = 0;
1333 defproxy.defsrv.maxconn = 0;
1334 defproxy.defsrv.slowstart = 0;
1335 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1336 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1337 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338}
1339
Willy Tarreauade5ec42010-01-28 19:33:49 +01001340
1341static int create_cond_regex_rule(const char *file, int line,
1342 struct proxy *px, int dir, int action, int flags,
1343 const char *cmd, const char *reg, const char *repl,
1344 const char **cond_start)
1345{
1346 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001347 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001348 const char *err;
1349 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001350 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001351
1352 if (px == &defproxy) {
1353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto err;
1356 }
1357
1358 if (*reg == 0) {
1359 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1365 err_code |= ERR_WARN;
1366
Willy Tarreau5321c422010-01-28 20:35:13 +01001367 if (cond_start &&
1368 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001369 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1370 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1371 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001372 err_code |= ERR_ALERT | ERR_FATAL;
1373 goto err;
1374 }
1375 }
1376 else if (cond_start && **cond_start) {
1377 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1378 file, line, cmd, *cond_start);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto err;
1381 }
1382
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001383 err_code |= warnif_cond_conflicts(cond,
1384 (dir == SMP_OPT_DIR_REQ) ?
1385 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1386 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1387 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001388
Willy Tarreauade5ec42010-01-28 19:33:49 +01001389 preg = calloc(1, sizeof(regex_t));
1390 if (!preg) {
1391 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1392 err_code = ERR_ALERT | ERR_FATAL;
1393 goto err;
1394 }
1395
1396 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1397 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1398 err_code = ERR_ALERT | ERR_FATAL;
1399 goto err;
1400 }
1401
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001402 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001403 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001404 if (repl && err) {
1405 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1406 file, line, cmd, *err);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 goto err;
1409 }
1410
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001411 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001412 err_code |= ERR_WARN;
1413
Willy Tarreauf4068b62012-05-08 17:37:49 +02001414 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001415 return err_code;
1416 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001417 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001418 free(preg);
1419 return err_code;
1420}
1421
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001424 * Returns the error code, 0 if OK, or any combination of :
1425 * - ERR_ABORT: must abort ASAP
1426 * - ERR_FATAL: we can continue parsing but not start the service
1427 * - ERR_WARN: a warning has been emitted
1428 * - ERR_ALERT: an alert has been emitted
1429 * Only the two first ones can stop processing, the two others are just
1430 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001432int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1433{
1434 static struct peers *curpeers = NULL;
1435 struct peer *newpeer = NULL;
1436 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001437 struct bind_conf *bind_conf;
1438 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001439 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001440 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001441
1442 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001443 if (!*args[1]) {
1444 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001448
1449 err = invalid_char(args[1]);
1450 if (err) {
1451 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1452 file, linenum, *err, args[0], args[1]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001454 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001455 }
1456
1457 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1458 /*
1459 * If there are two proxies with the same name only following
1460 * combinations are allowed:
1461 */
1462 if (strcmp(curpeers->id, args[1]) == 0) {
1463 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1464 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1465 err_code |= ERR_WARN;
1466 }
1467 }
1468
1469 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1471 err_code |= ERR_ALERT | ERR_ABORT;
1472 goto out;
1473 }
1474
1475 curpeers->next = peers;
1476 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001477 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001478 curpeers->conf.line = linenum;
1479 curpeers->last_change = now.tv_sec;
1480 curpeers->id = strdup(args[1]);
1481 }
1482 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001483 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001484 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001485 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001486
1487 if (!*args[2]) {
1488 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1489 file, linenum, args[0]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 err = invalid_char(args[1]);
1495 if (err) {
1496 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1497 file, linenum, *err, args[1]);
1498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1503 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1504 err_code |= ERR_ALERT | ERR_ABORT;
1505 goto out;
1506 }
1507
1508 /* the peers are linked backwards first */
1509 curpeers->count++;
1510 newpeer->next = curpeers->remote;
1511 curpeers->remote = newpeer;
1512 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001513 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001514 newpeer->conf.line = linenum;
1515
1516 newpeer->last_change = now.tv_sec;
1517 newpeer->id = strdup(args[1]);
1518
Willy Tarreau902636f2013-03-10 19:44:48 +01001519 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001520 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001521 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001524 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001525
1526 proto = protocol_by_family(sk->ss_family);
1527 if (!proto || !proto->connect) {
1528 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1529 file, linenum, args[0], args[1]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001533
1534 if (port1 != port2) {
1535 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1536 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
1540
Willy Tarreau2aa38802013-02-20 19:20:59 +01001541 if (!port1) {
1542 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1543 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001547
Emeric Brun32da3c42010-09-23 18:39:19 +02001548 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001549 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001550 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001551 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001552
Emeric Brun32da3c42010-09-23 18:39:19 +02001553 if (strcmp(newpeer->id, localpeer) == 0) {
1554 /* Current is local peer, it define a frontend */
1555 newpeer->local = 1;
1556
1557 if (!curpeers->peers_fe) {
1558 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1559 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1560 err_code |= ERR_ALERT | ERR_ABORT;
1561 goto out;
1562 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001563
Willy Tarreau237250c2011-07-29 01:49:03 +02001564 init_new_proxy(curpeers->peers_fe);
1565 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001566
1567 curpeers->peers_fe->last_change = now.tv_sec;
1568 curpeers->peers_fe->id = strdup(args[1]);
1569 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001570 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001571 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1572 curpeers->peers_fe->timeout.connect = 5000;
1573 curpeers->peers_fe->accept = peer_accept;
1574 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001575 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1576 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001577
1578 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1579
Willy Tarreau902636f2013-03-10 19:44:48 +01001580 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1581 if (errmsg && *errmsg) {
1582 indent_msg(&errmsg, 2);
1583 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001584 }
1585 else
1586 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1587 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001588 err_code |= ERR_FATAL;
1589 goto out;
1590 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001591
1592 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1593 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1594 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1595 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1596 l->accept = session_accept;
1597 l->handler = process_session;
1598 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1599 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1600 global.maxsock += l->maxconn;
1601 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001602 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001603 else {
1604 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1605 file, linenum, args[0], args[1],
1606 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1607 err_code |= ERR_FATAL;
1608 goto out;
1609 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001610 }
1611 } /* neither "peer" nor "peers" */
1612 else if (*args[0] != 0) {
1613 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1614 err_code |= ERR_ALERT | ERR_FATAL;
1615 goto out;
1616 }
1617
1618out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001619 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001620 return err_code;
1621}
1622
1623
Willy Tarreau3842f002009-06-14 11:39:52 +02001624int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625{
1626 static struct proxy *curproxy = NULL;
1627 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001628 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001629 int rc;
1630 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001631 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001632 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001633 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001634 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001635 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636
Willy Tarreau977b8e42006-12-29 14:19:17 +01001637 if (!strcmp(args[0], "listen"))
1638 rc = PR_CAP_LISTEN;
1639 else if (!strcmp(args[0], "frontend"))
1640 rc = PR_CAP_FE | PR_CAP_RS;
1641 else if (!strcmp(args[0], "backend"))
1642 rc = PR_CAP_BE | PR_CAP_RS;
1643 else if (!strcmp(args[0], "ruleset"))
1644 rc = PR_CAP_RS;
1645 else
1646 rc = PR_CAP_NONE;
1647
1648 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 if (!*args[1]) {
1650 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1651 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_ABORT;
1654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001656
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001657 err = invalid_char(args[1]);
1658 if (err) {
1659 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1660 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001661 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001662 }
1663
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001664 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1665 /*
1666 * If there are two proxies with the same name only following
1667 * combinations are allowed:
1668 *
1669 * listen backend frontend ruleset
1670 * listen - - - -
1671 * backend - - OK -
1672 * frontend - OK - -
1673 * ruleset - - - -
1674 */
1675
1676 if (!strcmp(curproxy->id, args[1]) &&
1677 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1678 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001679 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1680 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1681 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001682 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001683 }
1684 }
1685
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1687 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_ABORT;
1689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001691
Willy Tarreau97cb7802010-01-03 20:23:58 +01001692 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693 curproxy->next = proxy;
1694 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001695 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1696 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001697 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001699 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700
1701 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001703 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001704
Willy Tarreau4348fad2012-09-20 16:48:07 +02001705 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1706
Willy Tarreau902636f2013-03-10 19:44:48 +01001707 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1708 if (errmsg && *errmsg) {
1709 indent_msg(&errmsg, 2);
1710 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001711 }
1712 else
1713 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1714 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001715 err_code |= ERR_FATAL;
1716 goto out;
1717 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001718
Willy Tarreau4348fad2012-09-20 16:48:07 +02001719 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001720 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 }
1723
1724 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001725 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001726 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001727
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001730 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001731 curproxy->no_options = defproxy.no_options;
1732 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001733 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001734 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001735 curproxy->except_net = defproxy.except_net;
1736 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001737 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001738 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001740 if (defproxy.fwdfor_hdr_len) {
1741 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1742 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1743 }
1744
Willy Tarreaub86db342009-11-30 11:50:16 +01001745 if (defproxy.orgto_hdr_len) {
1746 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1747 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1748 }
1749
Mark Lamourinec2247f02012-01-04 13:02:01 -05001750 if (defproxy.server_id_hdr_len) {
1751 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1752 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1753 }
1754
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 if (curproxy->cap & PR_CAP_FE) {
1756 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001757 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001758 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001759
1760 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001761 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1762 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763
1764 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766
Willy Tarreau977b8e42006-12-29 14:19:17 +01001767 if (curproxy->cap & PR_CAP_BE) {
1768 curproxy->fullconn = defproxy.fullconn;
1769 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001771 if (defproxy.check_req) {
1772 curproxy->check_req = calloc(1, defproxy.check_len);
1773 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1774 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001775 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001777 if (defproxy.expect_str) {
1778 curproxy->expect_str = strdup(defproxy.expect_str);
1779 if (defproxy.expect_regex) {
1780 /* note: this regex is known to be valid */
1781 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1782 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1783 }
1784 }
1785
Willy Tarreau67402132012-05-31 20:40:20 +02001786 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 if (defproxy.cookie_name)
1788 curproxy->cookie_name = strdup(defproxy.cookie_name);
1789 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001790 if (defproxy.cookie_domain)
1791 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001792
Willy Tarreau31936852010-10-06 16:59:56 +02001793 if (defproxy.cookie_maxidle)
1794 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1795
1796 if (defproxy.cookie_maxlife)
1797 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1798
Emeric Brun647caf12009-06-30 17:57:00 +02001799 if (defproxy.rdp_cookie_name)
1800 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1801 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1802
Willy Tarreau01732802007-11-01 22:48:15 +01001803 if (defproxy.url_param_name)
1804 curproxy->url_param_name = strdup(defproxy.url_param_name);
1805 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001806
Benoitaffb4812009-03-25 13:02:10 +01001807 if (defproxy.hh_name)
1808 curproxy->hh_name = strdup(defproxy.hh_name);
1809 curproxy->hh_len = defproxy.hh_len;
1810 curproxy->hh_match_domain = defproxy.hh_match_domain;
1811
Willy Tarreauef9a3602012-12-08 22:29:20 +01001812 if (defproxy.conn_src.iface_name)
1813 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1814 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001815 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001816#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001817 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001818#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001820
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001821 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001822 if (defproxy.capture_name)
1823 curproxy->capture_name = strdup(defproxy.capture_name);
1824 curproxy->capture_namelen = defproxy.capture_namelen;
1825 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001826 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827
Willy Tarreau977b8e42006-12-29 14:19:17 +01001828 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001829 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001830 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001831 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001832 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833 curproxy->uri_auth = defproxy.uri_auth;
1834 curproxy->mon_net = defproxy.mon_net;
1835 curproxy->mon_mask = defproxy.mon_mask;
1836 if (defproxy.monitor_uri)
1837 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1838 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001839 if (defproxy.defbe.name)
1840 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001841
1842 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001843 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1844 if (curproxy->conf.logformat_string &&
1845 curproxy->conf.logformat_string != default_http_log_format &&
1846 curproxy->conf.logformat_string != default_tcp_log_format &&
1847 curproxy->conf.logformat_string != clf_http_log_format)
1848 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1849
1850 if (defproxy.conf.lfs_file) {
1851 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1852 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1853 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854 }
1855
1856 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001857 curproxy->timeout.connect = defproxy.timeout.connect;
1858 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001859 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001860 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001861 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001862 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001863 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001864 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001865 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001866 }
1867
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001869
1870 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001871 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001872 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001873 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001874 LIST_INIT(&node->list);
1875 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1876 }
1877
Willy Tarreau62a61232013-04-12 18:13:46 +02001878 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1879 if (curproxy->conf.uniqueid_format_string)
1880 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1881
1882 if (defproxy.conf.uif_file) {
1883 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1884 curproxy->conf.uif_line = defproxy.conf.uif_line;
1885 }
William Lallemanda73203e2012-03-12 12:48:57 +01001886
1887 /* copy default header unique id */
1888 if (defproxy.header_unique_id)
1889 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1890
William Lallemand82fe75c2012-10-23 10:25:10 +02001891 /* default compression options */
1892 if (defproxy.comp != NULL) {
1893 curproxy->comp = calloc(1, sizeof(struct comp));
1894 curproxy->comp->algos = defproxy.comp->algos;
1895 curproxy->comp->types = defproxy.comp->types;
1896 }
1897
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001899 curproxy->conf.used_listener_id = EB_ROOT;
1900 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001901
Willy Tarreau93893792009-07-23 13:19:11 +02001902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 }
1904 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1905 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001906 /* FIXME-20070101: we should do this too at the end of the
1907 * config parsing to free all default values.
1908 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001909 free(defproxy.check_req);
1910 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001911 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001912 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001913 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001914 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001915 free(defproxy.capture_name);
1916 free(defproxy.monitor_uri);
1917 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001918 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001919 free(defproxy.fwdfor_hdr_name);
1920 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001921 free(defproxy.orgto_hdr_name);
1922 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001923 free(defproxy.server_id_hdr_name);
1924 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001925 free(defproxy.expect_str);
1926 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001927
Willy Tarreau62a61232013-04-12 18:13:46 +02001928 if (defproxy.conf.logformat_string != default_http_log_format &&
1929 defproxy.conf.logformat_string != default_tcp_log_format &&
1930 defproxy.conf.logformat_string != clf_http_log_format)
1931 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001932
Willy Tarreau62a61232013-04-12 18:13:46 +02001933 free(defproxy.conf.uniqueid_format_string);
1934 free(defproxy.conf.lfs_file);
1935 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001936
Willy Tarreaua534fea2008-08-03 12:19:50 +02001937 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001938 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001939
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 /* we cannot free uri_auth because it might already be used */
1941 init_default_instance();
1942 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001943 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1944 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001945 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 }
1948 else if (curproxy == NULL) {
1949 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001953
1954 /* update the current file and line being parsed */
1955 curproxy->conf.args.file = curproxy->conf.file;
1956 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001957
1958 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001960 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001961 int cur_arg;
1962
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963 if (curproxy == &defproxy) {
1964 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_ALERT | ERR_FATAL;
1966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001968 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001969 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970
Willy Tarreau24709282013-03-10 21:32:12 +01001971 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001972 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001977
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001978 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001979
1980 /* use default settings for unix sockets */
1981 bind_conf->ux.uid = global.unix_bind.ux.uid;
1982 bind_conf->ux.gid = global.unix_bind.ux.gid;
1983 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001984
1985 /* NOTE: the following line might create several listeners if there
1986 * are comma-separated IPs or port ranges. So all further processing
1987 * will have to be applied to all listeners created after last_listen.
1988 */
Willy Tarreau902636f2013-03-10 19:44:48 +01001989 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
1990 if (errmsg && *errmsg) {
1991 indent_msg(&errmsg, 2);
1992 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001993 }
1994 else
1995 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1996 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001997 err_code |= ERR_ALERT | ERR_FATAL;
1998 goto out;
1999 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002000
Willy Tarreau4348fad2012-09-20 16:48:07 +02002001 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2002 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002003 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002004 }
2005
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002006 cur_arg = 2;
2007 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002008 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002009 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002010 char *err;
2011
Willy Tarreau26982662012-09-12 23:17:10 +02002012 kw = bind_find_kw(args[cur_arg]);
2013 if (kw) {
2014 char *err = NULL;
2015 int code;
2016
2017 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002018 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2019 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002020 cur_arg += 1 + kw->skip ;
2021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
2023 }
2024
Willy Tarreau4348fad2012-09-20 16:48:07 +02002025 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002026 err_code |= code;
2027
2028 if (code) {
2029 if (err && *err) {
2030 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002031 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002032 }
2033 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002034 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2035 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002036 if (code & ERR_FATAL) {
2037 free(err);
2038 cur_arg += 1 + kw->skip;
2039 goto out;
2040 }
2041 }
2042 free(err);
2043 cur_arg += 1 + kw->skip;
2044 continue;
2045 }
2046
Willy Tarreau8638f482012-09-18 18:01:17 +02002047 err = NULL;
2048 if (!bind_dumped) {
2049 bind_dump_kws(&err);
2050 indent_msg(&err, 4);
2051 bind_dumped = 1;
2052 }
2053
2054 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2055 file, linenum, args[0], args[1], args[cur_arg],
2056 err ? " Registered keywords :" : "", err ? err : "");
2057 free(err);
2058
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002061 }
Willy Tarreau93893792009-07-23 13:19:11 +02002062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 }
2064 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2065 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2066 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_ALERT | ERR_FATAL;
2069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002070 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002071 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002073
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 /* flush useless bits */
2075 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002078 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002080 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002081
Willy Tarreau1c47f852006-07-09 08:22:27 +02002082 if (!*args[1]) {
2083 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2084 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002087 }
2088
Willy Tarreaua534fea2008-08-03 12:19:50 +02002089 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002090 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002091 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002092 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002093 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2094
Willy Tarreau93893792009-07-23 13:19:11 +02002095 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2098 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2099 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2100 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2101 else {
2102 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 }
2106 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002107 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002108 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002109
2110 if (curproxy == &defproxy) {
2111 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2112 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002115 }
2116
2117 if (!*args[1]) {
2118 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2119 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002122 }
2123
2124 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002125 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002126
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002127 if (curproxy->uuid <= 0) {
2128 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002129 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_ALERT | ERR_FATAL;
2131 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002132 }
2133
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002134 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2135 if (node) {
2136 struct proxy *target = container_of(node, struct proxy, conf.id);
2137 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2138 file, linenum, proxy_type_str(curproxy), curproxy->id,
2139 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2140 err_code |= ERR_ALERT | ERR_FATAL;
2141 goto out;
2142 }
2143 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002144 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002145 else if (!strcmp(args[0], "description")) {
2146 int i, len=0;
2147 char *d;
2148
Cyril Bonté99ed3272010-01-24 23:29:44 +01002149 if (curproxy == &defproxy) {
2150 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2151 file, linenum, args[0]);
2152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
2154 }
2155
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002156 if (!*args[1]) {
2157 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2158 file, linenum, args[0]);
2159 return -1;
2160 }
2161
2162 for(i=1; *args[i]; i++)
2163 len += strlen(args[i])+1;
2164
2165 d = (char *)calloc(1, len);
2166 curproxy->desc = d;
2167
2168 d += sprintf(d, "%s", args[1]);
2169 for(i=2; *args[i]; i++)
2170 d += sprintf(d, " %s", args[i]);
2171
2172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2174 curproxy->state = PR_STSTOPPED;
2175 }
2176 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2177 curproxy->state = PR_STNEW;
2178 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002179 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2180 int cur_arg = 1;
2181 unsigned int set = 0;
2182
2183 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002184 unsigned int low, high;
2185
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002186 if (strcmp(args[cur_arg], "all") == 0) {
2187 set = 0;
2188 break;
2189 }
2190 else if (strcmp(args[cur_arg], "odd") == 0) {
2191 set |= 0x55555555;
2192 }
2193 else if (strcmp(args[cur_arg], "even") == 0) {
2194 set |= 0xAAAAAAAA;
2195 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002196 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002197 char *dash = strchr(args[cur_arg], '-');
2198
2199 low = high = str2uic(args[cur_arg]);
2200 if (dash)
2201 high = str2uic(dash + 1);
2202
2203 if (high < low) {
2204 unsigned int swap = low;
2205 low = high;
2206 high = swap;
2207 }
2208
2209 if (low < 1 || high > 32) {
2210 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002211 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002214 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002215
2216 if (high > global.nbproc) {
2217 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2218 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002220 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002221 while (low <= high)
2222 set |= 1 << (low++ - 1);
2223 }
2224 else {
2225 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2226 file, linenum, args[0]);
2227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002229 }
2230 cur_arg++;
2231 }
2232 curproxy->bind_proc = set;
2233 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002234 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002235 if (curproxy == &defproxy) {
2236 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002239 }
2240
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002241 err = invalid_char(args[1]);
2242 if (err) {
2243 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2244 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002245 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002246 }
2247
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002248 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002249 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2250 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002253 }
2254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2256 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257
Willy Tarreau977b8e42006-12-29 14:19:17 +01002258 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002260
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 if (*(args[1]) == 0) {
2262 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2263 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002267
Willy Tarreau67402132012-05-31 20:40:20 +02002268 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002269 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002270 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002271 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 curproxy->cookie_name = strdup(args[1]);
2273 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002274
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 cur_arg = 2;
2276 while (*(args[cur_arg])) {
2277 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002278 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }
2280 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002281 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 }
2283 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002284 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 }
2286 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002287 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 }
2289 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002290 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002292 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002293 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002296 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002298 else if (!strcmp(args[cur_arg], "httponly")) {
2299 curproxy->ck_opts |= PR_CK_HTTPONLY;
2300 }
2301 else if (!strcmp(args[cur_arg], "secure")) {
2302 curproxy->ck_opts |= PR_CK_SECURE;
2303 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002304 else if (!strcmp(args[cur_arg], "domain")) {
2305 if (!*args[cur_arg + 1]) {
2306 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2307 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002310 }
2311
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002312 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002313 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002314 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2315 " dots nor does not start with a dot."
2316 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002317 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002318 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002319 }
2320
2321 err = invalid_domainchar(args[cur_arg + 1]);
2322 if (err) {
2323 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2324 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002327 }
2328
Willy Tarreau68a897b2009-12-03 23:28:34 +01002329 if (!curproxy->cookie_domain) {
2330 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2331 } else {
2332 /* one domain was already specified, add another one by
2333 * building the string which will be returned along with
2334 * the cookie.
2335 */
2336 char *new_ptr;
2337 int new_len = strlen(curproxy->cookie_domain) +
2338 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2339 new_ptr = malloc(new_len);
2340 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2341 free(curproxy->cookie_domain);
2342 curproxy->cookie_domain = new_ptr;
2343 }
Willy Tarreau31936852010-10-06 16:59:56 +02002344 cur_arg++;
2345 }
2346 else if (!strcmp(args[cur_arg], "maxidle")) {
2347 unsigned int maxidle;
2348 const char *res;
2349
2350 if (!*args[cur_arg + 1]) {
2351 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2352 file, linenum, args[cur_arg]);
2353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
2355 }
2356
2357 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2358 if (res) {
2359 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2360 file, linenum, *res, args[cur_arg]);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364 curproxy->cookie_maxidle = maxidle;
2365 cur_arg++;
2366 }
2367 else if (!strcmp(args[cur_arg], "maxlife")) {
2368 unsigned int maxlife;
2369 const char *res;
2370
2371 if (!*args[cur_arg + 1]) {
2372 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2373 file, linenum, args[cur_arg]);
2374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
2376 }
2377
2378 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2379 if (res) {
2380 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2381 file, linenum, *res, args[cur_arg]);
2382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
2384 }
2385 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002386 cur_arg++;
2387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002389 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394 cur_arg++;
2395 }
Willy Tarreau67402132012-05-31 20:40:20 +02002396 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2398 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401
Willy Tarreau67402132012-05-31 20:40:20 +02002402 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2404 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002407
Willy Tarreau67402132012-05-31 20:40:20 +02002408 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002409 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2410 file, linenum);
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002414 else if (!strcmp(args[0], "persist")) { /* persist */
2415 if (*(args[1]) == 0) {
2416 Alert("parsing [%s:%d] : missing persist method.\n",
2417 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002420 }
2421
2422 if (!strncmp(args[1], "rdp-cookie", 10)) {
2423 curproxy->options2 |= PR_O2_RDPC_PRST;
2424
Emeric Brunb982a3d2010-01-04 15:45:53 +01002425 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002426 const char *beg, *end;
2427
2428 beg = args[1] + 11;
2429 end = strchr(beg, ')');
2430
2431 if (!end || end == beg) {
2432 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2433 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002436 }
2437
2438 free(curproxy->rdp_cookie_name);
2439 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2440 curproxy->rdp_cookie_len = end-beg;
2441 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002442 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002443 free(curproxy->rdp_cookie_name);
2444 curproxy->rdp_cookie_name = strdup("msts");
2445 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2446 }
2447 else { /* syntax */
2448 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2449 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002452 }
2453 }
2454 else {
2455 Alert("parsing [%s:%d] : unknown persist method.\n",
2456 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002459 }
2460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002462 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002464 if (curproxy == &defproxy) {
2465 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
2469
Willy Tarreau977b8e42006-12-29 14:19:17 +01002470 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002472
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002474 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 }
2479 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002480 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 curproxy->appsession_name = strdup(args[1]);
2482 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2483 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002484 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2485 if (err) {
2486 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2487 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002490 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002491 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002492
Willy Tarreau51041c72007-09-09 21:56:53 +02002493 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2494 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002495 err_code |= ERR_ALERT | ERR_ABORT;
2496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002498
2499 cur_arg = 6;
2500 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002501 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2502 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002503 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002504 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002505 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002506 } else if (!strcmp(args[cur_arg], "prefix")) {
2507 curproxy->options2 |= PR_O2_AS_PFX;
2508 } else if (!strcmp(args[cur_arg], "mode")) {
2509 if (!*args[cur_arg + 1]) {
2510 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2511 file, linenum, args[0], args[cur_arg]);
2512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
2514 }
2515
2516 cur_arg++;
2517 if (!strcmp(args[cur_arg], "query-string")) {
2518 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2519 curproxy->options2 |= PR_O2_AS_M_QS;
2520 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2521 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2522 curproxy->options2 |= PR_O2_AS_M_PP;
2523 } else {
2524 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
2527 }
2528 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002529 cur_arg++;
2530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 } /* Url App Session */
2532 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002533 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002535
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002537 if (curproxy == &defproxy) {
2538 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
2541 }
2542
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 if (*(args[4]) == 0) {
2544 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2545 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002549 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 curproxy->capture_name = strdup(args[2]);
2551 curproxy->capture_namelen = strlen(curproxy->capture_name);
2552 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 curproxy->to_log |= LW_COOKIE;
2554 }
2555 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2556 struct cap_hdr *hdr;
2557
2558 if (curproxy == &defproxy) {
2559 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 }
2563
2564 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2565 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2566 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
2570
2571 hdr = calloc(sizeof(struct cap_hdr), 1);
2572 hdr->next = curproxy->req_cap;
2573 hdr->name = strdup(args[3]);
2574 hdr->namelen = strlen(args[3]);
2575 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002576 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 hdr->index = curproxy->nb_req_cap++;
2578 curproxy->req_cap = hdr;
2579 curproxy->to_log |= LW_REQHDR;
2580 }
2581 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2582 struct cap_hdr *hdr;
2583
2584 if (curproxy == &defproxy) {
2585 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
2589
2590 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2591 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2592 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596 hdr = calloc(sizeof(struct cap_hdr), 1);
2597 hdr->next = curproxy->rsp_cap;
2598 hdr->name = strdup(args[3]);
2599 hdr->namelen = strlen(args[3]);
2600 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002601 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 hdr->index = curproxy->nb_rsp_cap++;
2603 curproxy->rsp_cap = hdr;
2604 curproxy->to_log |= LW_RSPHDR;
2605 }
2606 else {
2607 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2608 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 }
2612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002614 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002616
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 if (*(args[1]) == 0) {
2618 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
2623 curproxy->conn_retries = atol(args[1]);
2624 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002625 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002626 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002627
2628 if (curproxy == &defproxy) {
2629 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
2633
Willy Tarreau20b0de52012-12-24 15:45:22 +01002634 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2635 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2636 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2637 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2638 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2639 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 +01002640 file, linenum, args[0]);
2641 err_code |= ERR_WARN;
2642 }
2643
Willy Tarreauff011f22011-01-06 17:51:27 +01002644 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002645
Willy Tarreauff011f22011-01-06 17:51:27 +01002646 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002647 err_code |= ERR_ALERT | ERR_ABORT;
2648 goto out;
2649 }
2650
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002651 err_code |= warnif_cond_conflicts(rule->cond,
2652 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2653 file, linenum);
2654
Willy Tarreauff011f22011-01-06 17:51:27 +01002655 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002656 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002657 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2658 /* set the header name and length into the proxy structure */
2659 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2660 err_code |= ERR_WARN;
2661
2662 if (!*args[1]) {
2663 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2664 file, linenum, args[0]);
2665 err_code |= ERR_ALERT | ERR_FATAL;
2666 goto out;
2667 }
2668
2669 /* set the desired header name */
2670 free(curproxy->server_id_hdr_name);
2671 curproxy->server_id_hdr_name = strdup(args[1]);
2672 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2673 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002674 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002675 if (curproxy == &defproxy) {
2676 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002679 }
2680
Willy Tarreauef6494c2010-01-28 17:12:36 +01002681 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002682 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2683 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002684 err_code |= ERR_ALERT | ERR_FATAL;
2685 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002686 }
2687
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002688 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2689 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2690 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002691 err_code |= ERR_ALERT | ERR_FATAL;
2692 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002693 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002694
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002695 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002696 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002697 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002698 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002699 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002700
Cyril Bonté99ed3272010-01-24 23:29:44 +01002701 if (curproxy == &defproxy) {
2702 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
2705 }
2706
Willy Tarreau4baae242012-12-27 12:00:31 +01002707 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2708 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2709 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002712 }
2713
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002714 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002715 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002716 err_code |= warnif_cond_conflicts(rule->cond,
2717 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2718 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002719 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002720 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002721 struct switching_rule *rule;
2722
Willy Tarreaub099aca2008-10-12 17:26:37 +02002723 if (curproxy == &defproxy) {
2724 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002727 }
2728
Willy Tarreau55ea7572007-06-17 19:56:27 +02002729 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002730 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002731
2732 if (*(args[1]) == 0) {
2733 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002736 }
2737
Willy Tarreauef6494c2010-01-28 17:12:36 +01002738 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002739 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2740 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002743 }
2744
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002745 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2746 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2747 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002750 }
2751
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002752 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002753
Willy Tarreau55ea7572007-06-17 19:56:27 +02002754 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2755 rule->cond = cond;
2756 rule->be.name = strdup(args[1]);
2757 LIST_INIT(&rule->list);
2758 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2759 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002760 else if (strcmp(args[0], "use-server") == 0) {
2761 struct server_rule *rule;
2762
2763 if (curproxy == &defproxy) {
2764 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
2767 }
2768
2769 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2770 err_code |= ERR_WARN;
2771
2772 if (*(args[1]) == 0) {
2773 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
2776 }
2777
2778 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2779 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2780 file, linenum, args[0]);
2781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
2783 }
2784
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002785 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2786 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2787 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
2790 }
2791
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002792 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002793
2794 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2795 rule->cond = cond;
2796 rule->srv.name = strdup(args[1]);
2797 LIST_INIT(&rule->list);
2798 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2799 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2800 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002801 else if ((!strcmp(args[0], "force-persist")) ||
2802 (!strcmp(args[0], "ignore-persist"))) {
2803 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002804
2805 if (curproxy == &defproxy) {
2806 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2807 err_code |= ERR_ALERT | ERR_FATAL;
2808 goto out;
2809 }
2810
2811 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2812 err_code |= ERR_WARN;
2813
Willy Tarreauef6494c2010-01-28 17:12:36 +01002814 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002815 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2816 file, linenum, args[0]);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
2819 }
2820
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002821 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2822 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2823 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
2826 }
2827
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002828 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2829 * where force-persist is applied.
2830 */
2831 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002832
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002833 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002834 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002835 if (!strcmp(args[0], "force-persist")) {
2836 rule->type = PERSIST_TYPE_FORCE;
2837 } else {
2838 rule->type = PERSIST_TYPE_IGNORE;
2839 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002840 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002841 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002842 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002843 else if (!strcmp(args[0], "stick-table")) {
2844 int myidx = 1;
2845
Emeric Brun32da3c42010-09-23 18:39:19 +02002846 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002847 curproxy->table.type = (unsigned int)-1;
2848 while (*args[myidx]) {
2849 const char *err;
2850
2851 if (strcmp(args[myidx], "size") == 0) {
2852 myidx++;
2853 if (!*(args[myidx])) {
2854 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2855 file, linenum, args[myidx-1]);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
2859 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2860 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2861 file, linenum, *err, args[myidx-1]);
2862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
2864 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002865 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002866 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002867 else if (strcmp(args[myidx], "peers") == 0) {
2868 myidx++;
2869 if (!*(args[myidx])) {
2870 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2871 file, linenum, args[myidx-1]);
2872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
2874 }
2875 curproxy->table.peers.name = strdup(args[myidx++]);
2876 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002877 else if (strcmp(args[myidx], "expire") == 0) {
2878 myidx++;
2879 if (!*(args[myidx])) {
2880 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2881 file, linenum, args[myidx-1]);
2882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
2884 }
2885 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2886 if (err) {
2887 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2888 file, linenum, *err, args[myidx-1]);
2889 err_code |= ERR_ALERT | ERR_FATAL;
2890 goto out;
2891 }
2892 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002893 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002894 }
2895 else if (strcmp(args[myidx], "nopurge") == 0) {
2896 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002897 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002898 }
2899 else if (strcmp(args[myidx], "type") == 0) {
2900 myidx++;
2901 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2902 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2903 file, linenum, args[myidx]);
2904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
2906 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002907 /* myidx already points to next arg */
2908 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002909 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002910 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002911 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002912
2913 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002914 nw = args[myidx];
2915 while (*nw) {
2916 /* the "store" keyword supports a comma-separated list */
2917 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002918 sa = NULL; /* store arg */
2919 while (*nw && *nw != ',') {
2920 if (*nw == '(') {
2921 *nw = 0;
2922 sa = ++nw;
2923 while (*nw != ')') {
2924 if (!*nw) {
2925 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2926 file, linenum, args[0], cw);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930 nw++;
2931 }
2932 *nw = '\0';
2933 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002934 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002935 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002936 if (*nw)
2937 *nw++ = '\0';
2938 type = stktable_get_data_type(cw);
2939 if (type < 0) {
2940 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2941 file, linenum, args[0], cw);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
Willy Tarreauac782882010-06-20 10:41:54 +02002945
2946 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2947 switch (err) {
2948 case PE_NONE: break;
2949 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002950 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2951 file, linenum, args[0], cw);
2952 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002953 break;
2954
2955 case PE_ARG_MISSING:
2956 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2957 file, linenum, args[0], cw);
2958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
2960
2961 case PE_ARG_NOT_USED:
2962 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2963 file, linenum, args[0], cw);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
2966
2967 default:
2968 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2969 file, linenum, args[0], cw);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002972 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002973 }
2974 myidx++;
2975 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002976 else {
2977 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2978 file, linenum, args[myidx]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002981 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002982 }
2983
2984 if (!curproxy->table.size) {
2985 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2986 file, linenum);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990
2991 if (curproxy->table.type == (unsigned int)-1) {
2992 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2993 file, linenum);
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997 }
2998 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002999 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003000 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003001 int myidx = 0;
3002 const char *name = NULL;
3003 int flags;
3004
3005 if (curproxy == &defproxy) {
3006 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
3009 }
3010
3011 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3012 err_code |= ERR_WARN;
3013 goto out;
3014 }
3015
3016 myidx++;
3017 if ((strcmp(args[myidx], "store") == 0) ||
3018 (strcmp(args[myidx], "store-request") == 0)) {
3019 myidx++;
3020 flags = STK_IS_STORE;
3021 }
3022 else if (strcmp(args[myidx], "store-response") == 0) {
3023 myidx++;
3024 flags = STK_IS_STORE | STK_ON_RSP;
3025 }
3026 else if (strcmp(args[myidx], "match") == 0) {
3027 myidx++;
3028 flags = STK_IS_MATCH;
3029 }
3030 else if (strcmp(args[myidx], "on") == 0) {
3031 myidx++;
3032 flags = STK_IS_MATCH | STK_IS_STORE;
3033 }
3034 else {
3035 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
3038 }
3039
3040 if (*(args[myidx]) == 0) {
3041 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
3044 }
3045
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003046 curproxy->conf.args.ctx = ARGC_STK;
3047 expr = sample_parse_expr(args, &myidx, trash.str, trash.size, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003049 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 }
3053
3054 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003055 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3056 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3057 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003058 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003059 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003060 goto out;
3061 }
3062 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003063 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3064 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3065 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003066 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003067 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003068 goto out;
3069 }
3070 }
3071
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003072 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003073 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003074
Emeric Brunb982a3d2010-01-04 15:45:53 +01003075 if (strcmp(args[myidx], "table") == 0) {
3076 myidx++;
3077 name = args[myidx++];
3078 }
3079
Willy Tarreauef6494c2010-01-28 17:12:36 +01003080 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003081 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3082 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3083 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003084 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003085 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003086 goto out;
3087 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003088 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003089 else if (*(args[myidx])) {
3090 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3091 file, linenum, args[0], args[myidx]);
3092 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003093 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003094 goto out;
3095 }
Emeric Brun97679e72010-09-23 17:56:44 +02003096 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003097 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003098 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003099 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003100
Emeric Brunb982a3d2010-01-04 15:45:53 +01003101 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3102 rule->cond = cond;
3103 rule->expr = expr;
3104 rule->flags = flags;
3105 rule->table.name = name ? strdup(name) : NULL;
3106 LIST_INIT(&rule->list);
3107 if (flags & STK_ON_RSP)
3108 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3109 else
3110 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003113 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003115
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3117 curproxy->uri_auth = NULL; /* we must detach from the default config */
3118
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003119 if (!*args[1]) {
3120 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003121 } else if (!strcmp(args[1], "admin")) {
3122 struct stats_admin_rule *rule;
3123
3124 if (curproxy == &defproxy) {
3125 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
3128 }
3129
3130 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3131 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3132 err_code |= ERR_ALERT | ERR_ABORT;
3133 goto out;
3134 }
3135
3136 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3137 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3138 file, linenum, args[0], args[1]);
3139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
3141 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003142 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3143 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3144 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
3147 }
3148
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003149 err_code |= warnif_cond_conflicts(cond,
3150 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3151 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003152
3153 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3154 rule->cond = cond;
3155 LIST_INIT(&rule->list);
3156 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 } else if (!strcmp(args[1], "uri")) {
3158 if (*(args[2]) == 0) {
3159 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3163 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_ALERT | ERR_ABORT;
3165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 }
3167 } else if (!strcmp(args[1], "realm")) {
3168 if (*(args[2]) == 0) {
3169 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_ALERT | ERR_FATAL;
3171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3173 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_ABORT;
3175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003177 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003178 unsigned interval;
3179
3180 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3181 if (err) {
3182 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3183 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003186 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3187 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_ABORT;
3189 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003190 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003191 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003192 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003193
3194 if (curproxy == &defproxy) {
3195 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
3198 }
3199
3200 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3201 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3202 err_code |= ERR_ALERT | ERR_ABORT;
3203 goto out;
3204 }
3205
Willy Tarreauff011f22011-01-06 17:51:27 +01003206 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3207 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003208 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3209 file, linenum, args[0]);
3210 err_code |= ERR_WARN;
3211 }
3212
Willy Tarreauff011f22011-01-06 17:51:27 +01003213 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003214
Willy Tarreauff011f22011-01-06 17:51:27 +01003215 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003216 err_code |= ERR_ALERT | ERR_ABORT;
3217 goto out;
3218 }
3219
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003220 err_code |= warnif_cond_conflicts(rule->cond,
3221 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3222 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003223 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003224
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 } else if (!strcmp(args[1], "auth")) {
3226 if (*(args[2]) == 0) {
3227 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3231 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003232 err_code |= ERR_ALERT | ERR_ABORT;
3233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003234 }
3235 } else if (!strcmp(args[1], "scope")) {
3236 if (*(args[2]) == 0) {
3237 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3241 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003242 err_code |= ERR_ALERT | ERR_ABORT;
3243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 }
3245 } else if (!strcmp(args[1], "enable")) {
3246 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3247 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003248 err_code |= ERR_ALERT | ERR_ABORT;
3249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003251 } else if (!strcmp(args[1], "hide-version")) {
3252 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3253 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_ABORT;
3255 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003256 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003257 } else if (!strcmp(args[1], "show-legends")) {
3258 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3259 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3260 err_code |= ERR_ALERT | ERR_ABORT;
3261 goto out;
3262 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003263 } else if (!strcmp(args[1], "show-node")) {
3264
3265 if (*args[2]) {
3266 int i;
3267 char c;
3268
3269 for (i=0; args[2][i]; i++) {
3270 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003271 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3272 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003273 break;
3274 }
3275
3276 if (!i || args[2][i]) {
3277 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3278 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3279 file, linenum, args[0], args[1]);
3280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
3282 }
3283 }
3284
3285 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3286 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3287 err_code |= ERR_ALERT | ERR_ABORT;
3288 goto out;
3289 }
3290 } else if (!strcmp(args[1], "show-desc")) {
3291 char *desc = NULL;
3292
3293 if (*args[2]) {
3294 int i, len=0;
3295 char *d;
3296
3297 for(i=2; *args[i]; i++)
3298 len += strlen(args[i])+1;
3299
3300 desc = d = (char *)calloc(1, len);
3301
3302 d += sprintf(d, "%s", args[2]);
3303 for(i=3; *args[i]; i++)
3304 d += sprintf(d, " %s", args[i]);
3305 }
3306
3307 if (!*args[2] && !global.desc)
3308 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3309 file, linenum, args[1]);
3310 else {
3311 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3312 free(desc);
3313 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3314 err_code |= ERR_ALERT | ERR_ABORT;
3315 goto out;
3316 }
3317 free(desc);
3318 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003320stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003321 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 +01003322 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_ALERT | ERR_FATAL;
3324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 }
3326 }
3327 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003328 int optnum;
3329
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003330 if (*(args[1]) == '\0') {
3331 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3332 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003336
3337 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3338 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003339 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3340 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3341 file, linenum, cfg_opts[optnum].name);
3342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
3344 }
Willy Tarreau93893792009-07-23 13:19:11 +02003345 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3346 err_code |= ERR_WARN;
3347 goto out;
3348 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003349
Willy Tarreau3842f002009-06-14 11:39:52 +02003350 curproxy->no_options &= ~cfg_opts[optnum].val;
3351 curproxy->options &= ~cfg_opts[optnum].val;
3352
3353 switch (kwm) {
3354 case KWM_STD:
3355 curproxy->options |= cfg_opts[optnum].val;
3356 break;
3357 case KWM_NO:
3358 curproxy->no_options |= cfg_opts[optnum].val;
3359 break;
3360 case KWM_DEF: /* already cleared */
3361 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003362 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003363
Willy Tarreau93893792009-07-23 13:19:11 +02003364 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003365 }
3366 }
3367
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003368 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3369 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003370 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3371 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3372 file, linenum, cfg_opts2[optnum].name);
3373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
3375 }
Willy Tarreau93893792009-07-23 13:19:11 +02003376 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3377 err_code |= ERR_WARN;
3378 goto out;
3379 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003380
Willy Tarreau3842f002009-06-14 11:39:52 +02003381 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3382 curproxy->options2 &= ~cfg_opts2[optnum].val;
3383
3384 switch (kwm) {
3385 case KWM_STD:
3386 curproxy->options2 |= cfg_opts2[optnum].val;
3387 break;
3388 case KWM_NO:
3389 curproxy->no_options2 |= cfg_opts2[optnum].val;
3390 break;
3391 case KWM_DEF: /* already cleared */
3392 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003393 }
Willy Tarreau93893792009-07-23 13:19:11 +02003394 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003395 }
3396 }
3397
Willy Tarreau3842f002009-06-14 11:39:52 +02003398 if (kwm != KWM_STD) {
3399 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003400 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003403 }
3404
Emeric Brun3a058f32009-06-30 18:26:00 +02003405 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003406 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003408 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003409 if (*(args[2]) != '\0') {
3410 if (!strcmp(args[2], "clf")) {
3411 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003412 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003413 } else {
3414 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003417 }
3418 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003419 if (curproxy->conf.logformat_string != default_http_log_format &&
3420 curproxy->conf.logformat_string != default_tcp_log_format &&
3421 curproxy->conf.logformat_string != clf_http_log_format)
3422 free(curproxy->conf.logformat_string);
3423 curproxy->conf.logformat_string = logformat;
3424
3425 free(curproxy->conf.lfs_file);
3426 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3427 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003428 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003429 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003430 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003431 if (curproxy->conf.logformat_string != default_http_log_format &&
3432 curproxy->conf.logformat_string != default_tcp_log_format &&
3433 curproxy->conf.logformat_string != clf_http_log_format)
3434 free(curproxy->conf.logformat_string);
3435 curproxy->conf.logformat_string = default_tcp_log_format;
3436
3437 free(curproxy->conf.lfs_file);
3438 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3439 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 else if (!strcmp(args[1], "tcpka")) {
3442 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003443 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003444 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003445
3446 if (curproxy->cap & PR_CAP_FE)
3447 curproxy->options |= PR_O_TCP_CLI_KA;
3448 if (curproxy->cap & PR_CAP_BE)
3449 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003450 }
3451 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003452 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003453 err_code |= ERR_WARN;
3454
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003456 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003457 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003458 curproxy->options2 &= ~PR_O2_CHK_ANY;
3459 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003460 if (!*args[2]) { /* no argument */
3461 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3462 curproxy->check_len = strlen(DEF_CHECK_REQ);
3463 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003464 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 curproxy->check_req = (char *)malloc(reqlen);
3466 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003467 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003468 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003469 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003470 if (*args[4])
3471 reqlen += strlen(args[4]);
3472 else
3473 reqlen += strlen("HTTP/1.0");
3474
3475 curproxy->check_req = (char *)malloc(reqlen);
3476 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003477 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003479 }
3480 else if (!strcmp(args[1], "ssl-hello-chk")) {
3481 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003482 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003483 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003484
Willy Tarreaua534fea2008-08-03 12:19:50 +02003485 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003486 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003487 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003488 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 }
Willy Tarreau23677902007-05-08 23:50:35 +02003490 else if (!strcmp(args[1], "smtpchk")) {
3491 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003492 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003493 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003494 curproxy->options2 &= ~PR_O2_CHK_ANY;
3495 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003496
3497 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3498 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3499 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3500 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3501 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3502 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3503 curproxy->check_req = (char *)malloc(reqlen);
3504 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3505 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3506 } else {
3507 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3508 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3509 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3510 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3511 }
3512 }
3513 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003514 else if (!strcmp(args[1], "lb-agent-chk")) {
3515 /* use dynmaic health check */
3516 free(curproxy->check_req);
3517 curproxy->check_req = NULL;
3518 curproxy->options2 &= ~PR_O2_CHK_ANY;
3519 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3520 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003521 else if (!strcmp(args[1], "pgsql-check")) {
3522 /* use PostgreSQL request to check servers' health */
3523 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3524 err_code |= ERR_WARN;
3525
3526 free(curproxy->check_req);
3527 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003528 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003529 curproxy->options2 |= PR_O2_PGSQL_CHK;
3530
3531 if (*(args[2])) {
3532 int cur_arg = 2;
3533
3534 while (*(args[cur_arg])) {
3535 if (strcmp(args[cur_arg], "user") == 0) {
3536 char * packet;
3537 uint32_t packet_len;
3538 uint32_t pv;
3539
3540 /* suboption header - needs additional argument for it */
3541 if (*(args[cur_arg+1]) == 0) {
3542 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3543 file, linenum, args[0], args[1], args[cur_arg]);
3544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
3546 }
3547
3548 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3549 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3550 pv = htonl(0x30000); /* protocol version 3.0 */
3551
3552 packet = (char*) calloc(1, packet_len);
3553
3554 memcpy(packet + 4, &pv, 4);
3555
3556 /* copy "user" */
3557 memcpy(packet + 8, "user", 4);
3558
3559 /* copy username */
3560 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3561
3562 free(curproxy->check_req);
3563 curproxy->check_req = packet;
3564 curproxy->check_len = packet_len;
3565
3566 packet_len = htonl(packet_len);
3567 memcpy(packet, &packet_len, 4);
3568 cur_arg += 2;
3569 } else {
3570 /* unknown suboption - catchall */
3571 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3572 file, linenum, args[0], args[1]);
3573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
3575 }
3576 } /* end while loop */
3577 }
3578 }
3579
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003580 else if (!strcmp(args[1], "redis-check")) {
3581 /* use REDIS PING request to check servers' health */
3582 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3583 err_code |= ERR_WARN;
3584
3585 free(curproxy->check_req);
3586 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003587 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003588 curproxy->options2 |= PR_O2_REDIS_CHK;
3589
3590 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3591 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3592 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3593 }
3594
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003595 else if (!strcmp(args[1], "mysql-check")) {
3596 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003597 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3598 err_code |= ERR_WARN;
3599
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003600 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003601 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003602 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003603 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003604
3605 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3606 * const char mysql40_client_auth_pkt[] = {
3607 * "\x0e\x00\x00" // packet length
3608 * "\x01" // packet number
3609 * "\x00\x00" // client capabilities
3610 * "\x00\x00\x01" // max packet
3611 * "haproxy\x00" // username (null terminated string)
3612 * "\x00" // filler (always 0x00)
3613 * "\x01\x00\x00" // packet length
3614 * "\x00" // packet number
3615 * "\x01" // COM_QUIT command
3616 * };
3617 */
3618
3619 if (*(args[2])) {
3620 int cur_arg = 2;
3621
3622 while (*(args[cur_arg])) {
3623 if (strcmp(args[cur_arg], "user") == 0) {
3624 char *mysqluser;
3625 int packetlen, reqlen, userlen;
3626
3627 /* suboption header - needs additional argument for it */
3628 if (*(args[cur_arg+1]) == 0) {
3629 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3630 file, linenum, args[0], args[1], args[cur_arg]);
3631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
3633 }
3634 mysqluser = args[cur_arg + 1];
3635 userlen = strlen(mysqluser);
3636 packetlen = userlen + 7;
3637 reqlen = packetlen + 9;
3638
3639 free(curproxy->check_req);
3640 curproxy->check_req = (char *)calloc(1, reqlen);
3641 curproxy->check_len = reqlen;
3642
3643 snprintf(curproxy->check_req, 4, "%c%c%c",
3644 ((unsigned char) packetlen & 0xff),
3645 ((unsigned char) (packetlen >> 8) & 0xff),
3646 ((unsigned char) (packetlen >> 16) & 0xff));
3647
3648 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003649 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003650 curproxy->check_req[8] = 1;
3651 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3652 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3653 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3654 cur_arg += 2;
3655 } else {
3656 /* unknown suboption - catchall */
3657 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3658 file, linenum, args[0], args[1]);
3659 err_code |= ERR_ALERT | ERR_FATAL;
3660 goto out;
3661 }
3662 } /* end while loop */
3663 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003664 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003665 else if (!strcmp(args[1], "ldap-check")) {
3666 /* use LDAP request to check servers' health */
3667 free(curproxy->check_req);
3668 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003669 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003670 curproxy->options2 |= PR_O2_LDAP_CHK;
3671
3672 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3673 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3674 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3675 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003676 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003677 int cur_arg;
3678
3679 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3680 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003681 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003682
Willy Tarreau87cf5142011-08-19 22:57:24 +02003683 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003684
3685 free(curproxy->fwdfor_hdr_name);
3686 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3687 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3688
3689 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3690 cur_arg = 2;
3691 while (*(args[cur_arg])) {
3692 if (!strcmp(args[cur_arg], "except")) {
3693 /* suboption except - needs additional argument for it */
3694 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3695 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3696 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003699 }
3700 /* flush useless bits */
3701 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003702 cur_arg += 2;
3703 } else if (!strcmp(args[cur_arg], "header")) {
3704 /* suboption header - needs additional argument for it */
3705 if (*(args[cur_arg+1]) == 0) {
3706 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3707 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003708 err_code |= ERR_ALERT | ERR_FATAL;
3709 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003710 }
3711 free(curproxy->fwdfor_hdr_name);
3712 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3713 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3714 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003715 } else if (!strcmp(args[cur_arg], "if-none")) {
3716 curproxy->options &= ~PR_O_FF_ALWAYS;
3717 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003718 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003719 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003720 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003721 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003724 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003725 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003726 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003727 else if (!strcmp(args[1], "originalto")) {
3728 int cur_arg;
3729
3730 /* insert x-original-to field, but not for the IP address listed as an except.
3731 * set default options (ie: bitfield, header name, etc)
3732 */
3733
3734 curproxy->options |= PR_O_ORGTO;
3735
3736 free(curproxy->orgto_hdr_name);
3737 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3738 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3739
Willy Tarreau87cf5142011-08-19 22:57:24 +02003740 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003741 cur_arg = 2;
3742 while (*(args[cur_arg])) {
3743 if (!strcmp(args[cur_arg], "except")) {
3744 /* suboption except - needs additional argument for it */
3745 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3746 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3747 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003750 }
3751 /* flush useless bits */
3752 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3753 cur_arg += 2;
3754 } else if (!strcmp(args[cur_arg], "header")) {
3755 /* suboption header - needs additional argument for it */
3756 if (*(args[cur_arg+1]) == 0) {
3757 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3758 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003761 }
3762 free(curproxy->orgto_hdr_name);
3763 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3764 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3765 cur_arg += 2;
3766 } else {
3767 /* unknown suboption - catchall */
3768 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3769 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003772 }
3773 } /* end while loop */
3774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 else {
3776 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 }
Willy Tarreau93893792009-07-23 13:19:11 +02003780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003782 else if (!strcmp(args[0], "default_backend")) {
3783 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003785
3786 if (*(args[1]) == 0) {
3787 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003790 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003791 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003792 curproxy->defbe.name = strdup(args[1]);
3793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003795 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003797
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003798 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3799 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003800 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 /* enable reconnections to dispatch */
3802 curproxy->options |= PR_O_REDISP;
3803 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003804 else if (!strcmp(args[0], "http-check")) {
3805 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003807
3808 if (strcmp(args[1], "disable-on-404") == 0) {
3809 /* enable a graceful server shutdown on an HTTP 404 response */
3810 curproxy->options |= PR_O_DISABLE404;
3811 }
Willy Tarreauef781042010-01-27 11:53:01 +01003812 else if (strcmp(args[1], "send-state") == 0) {
3813 /* enable emission of the apparent state of a server in HTTP checks */
3814 curproxy->options2 |= PR_O2_CHK_SNDST;
3815 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003816 else if (strcmp(args[1], "expect") == 0) {
3817 const char *ptr_arg;
3818 int cur_arg;
3819
3820 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3821 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824 }
3825
3826 cur_arg = 2;
3827 /* consider exclamation marks, sole or at the beginning of a word */
3828 while (*(ptr_arg = args[cur_arg])) {
3829 while (*ptr_arg == '!') {
3830 curproxy->options2 ^= PR_O2_EXP_INV;
3831 ptr_arg++;
3832 }
3833 if (*ptr_arg)
3834 break;
3835 cur_arg++;
3836 }
3837 /* now ptr_arg points to the beginning of a word past any possible
3838 * exclamation mark, and cur_arg is the argument which holds this word.
3839 */
3840 if (strcmp(ptr_arg, "status") == 0) {
3841 if (!*(args[cur_arg + 1])) {
3842 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3843 file, linenum, args[0], args[1], ptr_arg);
3844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
3846 }
3847 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003848 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003849 curproxy->expect_str = strdup(args[cur_arg + 1]);
3850 }
3851 else if (strcmp(ptr_arg, "string") == 0) {
3852 if (!*(args[cur_arg + 1])) {
3853 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3854 file, linenum, args[0], args[1], ptr_arg);
3855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
3857 }
3858 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003859 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003860 curproxy->expect_str = strdup(args[cur_arg + 1]);
3861 }
3862 else if (strcmp(ptr_arg, "rstatus") == 0) {
3863 if (!*(args[cur_arg + 1])) {
3864 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3865 file, linenum, args[0], args[1], ptr_arg);
3866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
3868 }
3869 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003870 free(curproxy->expect_str);
3871 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3872 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003873 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3874 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3875 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3876 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
3879 }
3880 }
3881 else if (strcmp(ptr_arg, "rstring") == 0) {
3882 if (!*(args[cur_arg + 1])) {
3883 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3884 file, linenum, args[0], args[1], ptr_arg);
3885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
3887 }
3888 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003889 free(curproxy->expect_str);
3890 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3891 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003892 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3893 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3894 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3895 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
3898 }
3899 }
3900 else {
3901 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3902 file, linenum, args[0], args[1], ptr_arg);
3903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
3905 }
3906 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003907 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003908 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 +02003909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003911 }
3912 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003913 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003914 if (curproxy == &defproxy) {
3915 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003918 }
3919
Willy Tarreaub80c2302007-11-30 20:51:32 +01003920 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003922
3923 if (strcmp(args[1], "fail") == 0) {
3924 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003925 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003926 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3927 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003930 }
3931
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003932 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3933 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3934 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003937 }
3938 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3939 }
3940 else {
3941 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003944 }
3945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946#ifdef TPROXY
3947 else if (!strcmp(args[0], "transparent")) {
3948 /* enable transparent proxy connections */
3949 curproxy->options |= PR_O_TRANSP;
3950 }
3951#endif
3952 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003953 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003954 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003955
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956 if (*(args[1]) == 0) {
3957 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 }
3961 curproxy->maxconn = atol(args[1]);
3962 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003963 else if (!strcmp(args[0], "backlog")) { /* backlog */
3964 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003965 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003966
3967 if (*(args[1]) == 0) {
3968 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003969 err_code |= ERR_ALERT | ERR_FATAL;
3970 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003971 }
3972 curproxy->backlog = atol(args[1]);
3973 }
Willy Tarreau86034312006-12-29 00:10:33 +01003974 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003975 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003976 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003977
Willy Tarreau86034312006-12-29 00:10:33 +01003978 if (*(args[1]) == 0) {
3979 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003982 }
3983 curproxy->fullconn = atol(args[1]);
3984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3986 if (*(args[1]) == 0) {
3987 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003991 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3992 if (err) {
3993 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3994 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003997 }
3998 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003999 }
4000 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004001 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004002 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004003 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004004
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 if (curproxy == &defproxy) {
4006 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004010 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004011 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004012
Willy Tarreau902636f2013-03-10 19:44:48 +01004013 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004014 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004015 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004017 goto out;
4018 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004019
4020 proto = protocol_by_family(sk->ss_family);
4021 if (!proto || !proto->connect) {
4022 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4023 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027
4028 if (port1 != port2) {
4029 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4030 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004034
4035 if (!port1) {
4036 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4037 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
4040 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004041
Willy Tarreaud5191e72010-02-09 20:50:45 +01004042 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004043 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 }
4045 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004046 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004048
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004049 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4050 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004055 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4056 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4057 err_code |= ERR_WARN;
4058
4059 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4060 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4061 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4062 }
4063 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4064 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4065 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4066 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004067 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4068 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4069 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4070 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004071 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004072 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004077 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004079 short realport = 0;
4080 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004082 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004083 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004087 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004088 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004089
4090 if (!*args[2]) {
4091 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4092 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004095 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004096
4097 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004098 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004099 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4100 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004103 }
4104
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004105 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004106 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004107 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004108 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004109
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004110 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4111 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4112 err_code |= ERR_ALERT | ERR_ABORT;
4113 goto out;
4114 }
4115
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004116 /* the servers are linked backwards first */
4117 newsrv->next = curproxy->srv;
4118 curproxy->srv = newsrv;
4119 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004120 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004121 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004122
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004123 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004124 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004125 LIST_INIT(&newsrv->pendconns);
4126 do_check = 0;
4127 newsrv->state = SRV_RUNNING; /* early server setup */
4128 newsrv->last_change = now.tv_sec;
4129 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004130
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004131 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004132 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004133 * - IP: => port=+0, relative
4134 * - IP:N => port=N, absolute
4135 * - IP:+N => port=+N, relative
4136 * - IP:-N => port=-N, relative
4137 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004138 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004139 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004140 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004141 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004142 goto out;
4143 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004144
4145 proto = protocol_by_family(sk->ss_family);
4146 if (!proto || !proto->connect) {
4147 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4148 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
4151 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004152
4153 if (!port1 || !port2) {
4154 /* no port specified, +offset, -offset */
4155 newsrv->state |= SRV_MAPPORTS;
4156 }
4157 else if (port1 != port2) {
4158 /* port range */
4159 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4160 file, linenum, args[0], args[1], args[2]);
4161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
4163 }
4164 else {
4165 /* used by checks */
4166 realport = port1;
4167 }
4168
Willy Tarreaud5191e72010-02-09 20:50:45 +01004169 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004170 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4171 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004172
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004173 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004174 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4175 file, linenum, newsrv->addr.ss_family, args[2]);
4176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
4178 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004179
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004180 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004181 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004182 newsrv->inter = curproxy->defsrv.inter;
4183 newsrv->fastinter = curproxy->defsrv.fastinter;
4184 newsrv->downinter = curproxy->defsrv.downinter;
4185 newsrv->rise = curproxy->defsrv.rise;
4186 newsrv->fall = curproxy->defsrv.fall;
4187 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4188 newsrv->minconn = curproxy->defsrv.minconn;
4189 newsrv->maxconn = curproxy->defsrv.maxconn;
4190 newsrv->slowstart = curproxy->defsrv.slowstart;
4191 newsrv->onerror = curproxy->defsrv.onerror;
4192 newsrv->consecutive_errors_limit
4193 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004194#ifdef OPENSSL
4195 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4196#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004197 newsrv->uweight = newsrv->iweight
4198 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004200 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004201
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004202 cur_arg = 3;
4203 } else {
4204 newsrv = &curproxy->defsrv;
4205 cur_arg = 1;
4206 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004207
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004209 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 newsrv->cookie = strdup(args[cur_arg + 1]);
4211 newsrv->cklen = strlen(args[cur_arg + 1]);
4212 cur_arg += 2;
4213 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004214 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004215 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4216 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4217 cur_arg += 2;
4218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004220 if (!*args[cur_arg + 1]) {
4221 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4222 file, linenum, args[cur_arg]);
4223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
4225 }
4226
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004228 if (newsrv->rise <= 0) {
4229 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4230 file, linenum, args[cur_arg]);
4231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
4233 }
4234
Willy Tarreau96839092010-03-29 10:02:24 +02004235 if (newsrv->health)
4236 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004237 cur_arg += 2;
4238 }
4239 else if (!strcmp(args[cur_arg], "fall")) {
4240 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004241
4242 if (!*args[cur_arg + 1]) {
4243 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4244 file, linenum, args[cur_arg]);
4245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
4247 }
4248
4249 if (newsrv->fall <= 0) {
4250 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4251 file, linenum, args[cur_arg]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255
Willy Tarreaubaaee002006-06-26 02:48:02 +02004256 cur_arg += 2;
4257 }
4258 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004259 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4260 if (err) {
4261 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4262 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004265 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004266 if (val <= 0) {
4267 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4268 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004271 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004272 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273 cur_arg += 2;
4274 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004275 else if (!strcmp(args[cur_arg], "fastinter")) {
4276 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4277 if (err) {
4278 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4279 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004282 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004283 if (val <= 0) {
4284 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4285 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004288 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004289 newsrv->fastinter = val;
4290 cur_arg += 2;
4291 }
4292 else if (!strcmp(args[cur_arg], "downinter")) {
4293 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4294 if (err) {
4295 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4296 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004299 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004300 if (val <= 0) {
4301 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4302 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004305 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004306 newsrv->downinter = val;
4307 cur_arg += 2;
4308 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004309 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004310 struct sockaddr_storage *sk;
4311 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004312 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004313
Willy Tarreau902636f2013-03-10 19:44:48 +01004314 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004315 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004316 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004317 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004318 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004319 goto out;
4320 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004321
4322 proto = protocol_by_family(sk->ss_family);
4323 if (!proto || !proto->connect) {
4324 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004325 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
4328 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004329
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004330 if (port1 != port2) {
4331 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4332 file, linenum, args[cur_arg], args[cur_arg + 1]);
4333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
4335 }
4336
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004337 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004338 cur_arg += 2;
4339 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004340 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004341 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342 cur_arg += 2;
4343 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004344 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 newsrv->state |= SRV_BACKUP;
4346 cur_arg ++;
4347 }
Simon Hormanfa461682011-06-25 09:39:49 +09004348 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4349 newsrv->state |= SRV_NON_STICK;
4350 cur_arg ++;
4351 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004352 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4353 newsrv->state |= SRV_SEND_PROXY;
4354 cur_arg ++;
4355 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004356 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4357 newsrv->check.send_proxy = 1;
4358 cur_arg ++;
4359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004360 else if (!strcmp(args[cur_arg], "weight")) {
4361 int w;
4362 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004363 if (w < 0 || w > 256) {
4364 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004365 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004368 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004369 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 cur_arg += 2;
4371 }
4372 else if (!strcmp(args[cur_arg], "minconn")) {
4373 newsrv->minconn = atol(args[cur_arg + 1]);
4374 cur_arg += 2;
4375 }
4376 else if (!strcmp(args[cur_arg], "maxconn")) {
4377 newsrv->maxconn = atol(args[cur_arg + 1]);
4378 cur_arg += 2;
4379 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004380 else if (!strcmp(args[cur_arg], "maxqueue")) {
4381 newsrv->maxqueue = atol(args[cur_arg + 1]);
4382 cur_arg += 2;
4383 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004384 else if (!strcmp(args[cur_arg], "slowstart")) {
4385 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004386 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004387 if (err) {
4388 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4389 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004392 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004393 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004394 cur_arg += 2;
4395 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004396 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004397
4398 if (!*args[cur_arg + 1]) {
4399 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4400 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004403 }
4404
4405 newsrv->trackit = strdup(args[cur_arg + 1]);
4406
4407 cur_arg += 2;
4408 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004409 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004410 global.maxsock++;
4411 do_check = 1;
4412 cur_arg += 1;
4413 }
Willy Tarreau96839092010-03-29 10:02:24 +02004414 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4415 newsrv->state |= SRV_MAINTAIN;
4416 newsrv->state &= ~SRV_RUNNING;
4417 newsrv->health = 0;
4418 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004419 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004420 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004421 if (!strcmp(args[cur_arg + 1], "none"))
4422 newsrv->observe = HANA_OBS_NONE;
4423 else if (!strcmp(args[cur_arg + 1], "layer4"))
4424 newsrv->observe = HANA_OBS_LAYER4;
4425 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4426 if (curproxy->mode != PR_MODE_HTTP) {
4427 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4428 file, linenum, args[cur_arg + 1]);
4429 err_code |= ERR_ALERT;
4430 }
4431 newsrv->observe = HANA_OBS_LAYER7;
4432 }
4433 else {
4434 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004435 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004436 file, linenum, args[cur_arg], args[cur_arg + 1]);
4437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
4439 }
4440
4441 cur_arg += 2;
4442 }
4443 else if (!strcmp(args[cur_arg], "on-error")) {
4444 if (!strcmp(args[cur_arg + 1], "fastinter"))
4445 newsrv->onerror = HANA_ONERR_FASTINTER;
4446 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4447 newsrv->onerror = HANA_ONERR_FAILCHK;
4448 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4449 newsrv->onerror = HANA_ONERR_SUDDTH;
4450 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4451 newsrv->onerror = HANA_ONERR_MARKDWN;
4452 else {
4453 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004454 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004455 file, linenum, args[cur_arg], args[cur_arg + 1]);
4456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
4458 }
4459
4460 cur_arg += 2;
4461 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004462 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4463 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4464 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4465 else {
4466 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4467 file, linenum, args[cur_arg], args[cur_arg + 1]);
4468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
4470 }
4471
4472 cur_arg += 2;
4473 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004474 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4475 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4476 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4477 else {
4478 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4479 file, linenum, args[cur_arg], args[cur_arg + 1]);
4480 err_code |= ERR_ALERT | ERR_FATAL;
4481 goto out;
4482 }
4483
4484 cur_arg += 2;
4485 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004486 else if (!strcmp(args[cur_arg], "error-limit")) {
4487 if (!*args[cur_arg + 1]) {
4488 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4489 file, linenum, args[cur_arg]);
4490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
4492 }
4493
4494 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4495
4496 if (newsrv->consecutive_errors_limit <= 0) {
4497 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4498 file, linenum, args[cur_arg]);
4499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
4501 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004502 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004503 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004504 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004505 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004506 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004507 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004508
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004510 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4511 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004515
Willy Tarreauef9a3602012-12-08 22:29:20 +01004516 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004517 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004518 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004519 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004520 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004521 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004522 goto out;
4523 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004524
4525 proto = protocol_by_family(sk->ss_family);
4526 if (!proto || !proto->connect) {
4527 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4528 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
4531 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004532
Willy Tarreauef9a3602012-12-08 22:29:20 +01004533 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004534
4535 if (port_low != port_high) {
4536 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004537
4538 if (!port_low || !port_high) {
4539 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4540 file, linenum, args[cur_arg], args[cur_arg + 1]);
4541 err_code |= ERR_ALERT | ERR_FATAL;
4542 goto out;
4543 }
4544
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004545 if (port_low <= 0 || port_low > 65535 ||
4546 port_high <= 0 || port_high > 65535 ||
4547 port_low > port_high) {
4548 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4549 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004550 err_code |= ERR_ALERT | ERR_FATAL;
4551 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004552 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004553 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4554 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4555 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004556 }
4557
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004559 while (*(args[cur_arg])) {
4560 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004561#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4562#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004563 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004564 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4565 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004568 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004569#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004570 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004571 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004572 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004575 }
4576 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004577 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4578 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004579 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004580 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4581 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004582 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4583 char *name, *end;
4584
4585 name = args[cur_arg+1] + 7;
4586 while (isspace(*name))
4587 name++;
4588
4589 end = name;
4590 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4591 end++;
4592
Willy Tarreauef9a3602012-12-08 22:29:20 +01004593 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4594 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4595 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4596 newsrv->conn_src.bind_hdr_len = end - name;
4597 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4598 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4599 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004600
4601 /* now look for an occurrence number */
4602 while (isspace(*end))
4603 end++;
4604 if (*end == ',') {
4605 end++;
4606 name = end;
4607 if (*end == '-')
4608 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004609 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004610 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004611 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004612 }
4613
Willy Tarreauef9a3602012-12-08 22:29:20 +01004614 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004615 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4616 " occurrences values smaller than %d.\n",
4617 file, linenum, MAX_HDR_HISTORY);
4618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
4620 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004621 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004622 struct sockaddr_storage *sk;
4623 int port1, port2;
4624
Willy Tarreau902636f2013-03-10 19:44:48 +01004625 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004626 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004627 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004628 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004629 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004630 goto out;
4631 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004632
4633 proto = protocol_by_family(sk->ss_family);
4634 if (!proto || !proto->connect) {
4635 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4636 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
4639 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004640
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004641 if (port1 != port2) {
4642 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4643 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004644 err_code |= ERR_ALERT | ERR_FATAL;
4645 goto out;
4646 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004647 newsrv->conn_src.tproxy_addr = *sk;
4648 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004649 }
4650 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004651#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004652 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004653#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004654 cur_arg += 2;
4655 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004656#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004657 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004658 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004661#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004662 } /* "usesrc" */
4663
4664 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4665#ifdef SO_BINDTODEVICE
4666 if (!*args[cur_arg + 1]) {
4667 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4668 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004671 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004672 free(newsrv->conn_src.iface_name);
4673 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4674 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004675 global.last_checks |= LSTCHK_NETADM;
4676#else
4677 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4678 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004679 err_code |= ERR_ALERT | ERR_FATAL;
4680 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004681#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004682 cur_arg += 2;
4683 continue;
4684 }
4685 /* this keyword in not an option of "source" */
4686 break;
4687 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004688 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004689 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004690 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4691 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004692 err_code |= ERR_ALERT | ERR_FATAL;
4693 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004696 static int srv_dumped;
4697 struct srv_kw *kw;
4698 char *err;
4699
4700 kw = srv_find_kw(args[cur_arg]);
4701 if (kw) {
4702 char *err = NULL;
4703 int code;
4704
4705 if (!kw->parse) {
4706 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4707 file, linenum, args[0], args[1], args[cur_arg]);
4708 cur_arg += 1 + kw->skip ;
4709 err_code |= ERR_ALERT | ERR_FATAL;
4710 goto out;
4711 }
4712
4713 if (defsrv && !kw->default_ok) {
4714 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4715 file, linenum, args[0], args[1], args[cur_arg]);
4716 cur_arg += 1 + kw->skip ;
4717 err_code |= ERR_ALERT;
4718 continue;
4719 }
4720
4721 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4722 err_code |= code;
4723
4724 if (code) {
4725 if (err && *err) {
4726 indent_msg(&err, 2);
4727 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4728 }
4729 else
4730 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4731 file, linenum, args[0], args[1], args[cur_arg]);
4732 if (code & ERR_FATAL) {
4733 free(err);
4734 cur_arg += 1 + kw->skip;
4735 goto out;
4736 }
4737 }
4738 free(err);
4739 cur_arg += 1 + kw->skip;
4740 continue;
4741 }
4742
4743 err = NULL;
4744 if (!srv_dumped) {
4745 srv_dump_kws(&err);
4746 indent_msg(&err, 4);
4747 srv_dumped = 1;
4748 }
4749
4750 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4751 file, linenum, args[0], args[1], args[cur_arg],
4752 err ? " Registered keywords :" : "", err ? err : "");
4753 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004754
Willy Tarreau93893792009-07-23 13:19:11 +02004755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
4758 }
4759
4760 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004761 if (newsrv->trackit) {
4762 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4763 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004766 }
4767
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004768 /* If neither a port nor an addr was specified and no check transport
4769 * layer is forced, then the transport layer used by the checks is the
4770 * same as for the production traffic. Otherwise we use raw_sock by
4771 * default, unless one is specified.
4772 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004773 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004774#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004775 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004776#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004777 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4778 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004779 /* try to get the port from check.addr if check.port not set */
4780 if (!newsrv->check.port)
4781 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004782
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004783 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004784 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004785
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004786 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004787 /* not yet valid, because no port was set on
4788 * the server either. We'll check if we have
4789 * a known port on the first listener.
4790 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004791 struct listener *l;
4792
4793 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004794 newsrv->check.port = get_host_port(&l->addr);
4795 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004796 break;
4797 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004798 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004799 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4801 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004805
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004806 /* Allocate buffer for check requests... */
4807 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004808 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4809 err_code |= ERR_ALERT | ERR_ABORT;
4810 goto out;
4811 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004812 newsrv->check.bi->size = global.tune.chksize;
4813
4814 /* Allocate buffer for check responses... */
4815 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4816 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4817 err_code |= ERR_ALERT | ERR_ABORT;
4818 goto out;
4819 }
4820 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004821
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004822 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004823 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004824 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4825 err_code |= ERR_ALERT | ERR_ABORT;
4826 goto out;
4827 }
4828
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004829 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4830 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 newsrv->state |= SRV_CHECKED;
4832 }
4833
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004834 if (!defsrv) {
4835 if (newsrv->state & SRV_BACKUP)
4836 curproxy->srv_bck++;
4837 else
4838 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004839
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004840 newsrv->prev_state = newsrv->state;
4841 }
William Lallemanda73203e2012-03-12 12:48:57 +01004842 }
4843
4844 else if (strcmp(args[0], "unique-id-format") == 0) {
4845 if (!*(args[1])) {
4846 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
4849 }
William Lallemand3203ff42012-11-11 17:30:56 +01004850 if (*(args[2])) {
4851 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4852 err_code |= ERR_ALERT | ERR_FATAL;
4853 goto out;
4854 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004855 free(curproxy->conf.uniqueid_format_string);
4856 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004857
Willy Tarreau62a61232013-04-12 18:13:46 +02004858 free(curproxy->conf.uif_file);
4859 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4860 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004861 }
William Lallemanda73203e2012-03-12 12:48:57 +01004862
4863 else if (strcmp(args[0], "unique-id-header") == 0) {
4864 if (!*(args[1])) {
4865 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
4868 }
4869 free(curproxy->header_unique_id);
4870 curproxy->header_unique_id = strdup(args[1]);
4871 }
4872
William Lallemand723b73a2012-02-08 16:37:49 +01004873 else if (strcmp(args[0], "log-format") == 0) {
4874 if (!*(args[1])) {
4875 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
4878 }
William Lallemand3203ff42012-11-11 17:30:56 +01004879 if (*(args[2])) {
4880 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4881 err_code |= ERR_ALERT | ERR_FATAL;
4882 goto out;
4883 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004884
Willy Tarreau62a61232013-04-12 18:13:46 +02004885 if (curproxy->conf.logformat_string != default_http_log_format &&
4886 curproxy->conf.logformat_string != default_tcp_log_format &&
4887 curproxy->conf.logformat_string != clf_http_log_format)
4888 free(curproxy->conf.logformat_string);
4889 curproxy->conf.logformat_string = strdup(args[1]);
4890
4891 free(curproxy->conf.lfs_file);
4892 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4893 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004894
4895 /* get a chance to improve log-format error reporting by
4896 * reporting the correct line-number when possible.
4897 */
4898 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4899 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4900 file, linenum, curproxy->id);
4901 err_code |= ERR_WARN;
4902 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 }
William Lallemand723b73a2012-02-08 16:37:49 +01004904
William Lallemand0f99e342011-10-12 17:50:54 +02004905 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4906 /* delete previous herited or defined syslog servers */
4907 struct logsrv *back;
4908
4909 if (*(args[1]) != 0) {
4910 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
4913 }
4914
William Lallemand723b73a2012-02-08 16:37:49 +01004915 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4916 LIST_DEL(&tmplogsrv->list);
4917 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004918 }
4919 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004921 struct logsrv *logsrv;
4922
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004924 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004925 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004926 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004927 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004928 LIST_INIT(&node->list);
4929 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 }
4932 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004933 struct sockaddr_storage *sk;
4934 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004935
4936 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937
William Lallemand0f99e342011-10-12 17:50:54 +02004938 logsrv->facility = get_log_facility(args[2]);
4939 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004941 err_code |= ERR_ALERT | ERR_FATAL;
4942 goto out;
4943
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
4945
William Lallemand0f99e342011-10-12 17:50:54 +02004946 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004948 logsrv->level = get_log_level(args[3]);
4949 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004951 err_code |= ERR_ALERT | ERR_FATAL;
4952 goto out;
4953
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 }
4955 }
4956
William Lallemand0f99e342011-10-12 17:50:54 +02004957 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004958 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004959 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004960 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004961 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004962 err_code |= ERR_ALERT | ERR_FATAL;
4963 goto out;
4964
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004965 }
4966 }
4967
Willy Tarreau902636f2013-03-10 19:44:48 +01004968 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004969 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004970 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004971 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004972 goto out;
4973 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004974
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004975 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004976
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004977 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004978 if (port1 != port2) {
4979 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4980 file, linenum, args[0], args[1]);
4981 err_code |= ERR_ALERT | ERR_FATAL;
4982 goto out;
4983 }
4984
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004985 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004986 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 }
William Lallemand0f99e342011-10-12 17:50:54 +02004988
4989 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 }
4991 else {
4992 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4993 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 }
4997 }
4998 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004999 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005000 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005001 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005002 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005003
Willy Tarreau977b8e42006-12-29 14:19:17 +01005004 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005005 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005006
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005008 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5009 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005010 err_code |= ERR_ALERT | ERR_FATAL;
5011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005013
5014 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005015 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5016 free(curproxy->conn_src.iface_name);
5017 curproxy->conn_src.iface_name = NULL;
5018 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005019
Willy Tarreau902636f2013-03-10 19:44:48 +01005020 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005021 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005022 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005023 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005024 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005025 goto out;
5026 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005027
5028 proto = protocol_by_family(sk->ss_family);
5029 if (!proto || !proto->connect) {
5030 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005031 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
5034 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005035
5036 if (port1 != port2) {
5037 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5038 file, linenum, args[0], args[1]);
5039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
5041 }
5042
Willy Tarreauef9a3602012-12-08 22:29:20 +01005043 curproxy->conn_src.source_addr = *sk;
5044 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005045
5046 cur_arg = 2;
5047 while (*(args[cur_arg])) {
5048 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005049#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5050#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005051 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005052 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5053 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005056 }
5057#endif
5058 if (!*args[cur_arg + 1]) {
5059 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5060 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005063 }
5064
5065 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005066 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5067 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005068 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005069 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5070 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005071 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5072 char *name, *end;
5073
5074 name = args[cur_arg+1] + 7;
5075 while (isspace(*name))
5076 name++;
5077
5078 end = name;
5079 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5080 end++;
5081
Willy Tarreauef9a3602012-12-08 22:29:20 +01005082 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5083 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5084 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5085 curproxy->conn_src.bind_hdr_len = end - name;
5086 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5087 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5088 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005089
5090 /* now look for an occurrence number */
5091 while (isspace(*end))
5092 end++;
5093 if (*end == ',') {
5094 end++;
5095 name = end;
5096 if (*end == '-')
5097 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005098 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005099 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005100 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005101 }
5102
Willy Tarreauef9a3602012-12-08 22:29:20 +01005103 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005104 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5105 " occurrences values smaller than %d.\n",
5106 file, linenum, MAX_HDR_HISTORY);
5107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005110 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005111 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005112
Willy Tarreau902636f2013-03-10 19:44:48 +01005113 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005114 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005115 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005116 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005117 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005118 goto out;
5119 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005120
5121 proto = protocol_by_family(sk->ss_family);
5122 if (!proto || !proto->connect) {
5123 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5124 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
5127 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005128
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005129 if (port1 != port2) {
5130 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5131 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
5134 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005135 curproxy->conn_src.tproxy_addr = *sk;
5136 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005137 }
5138 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005139#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005140 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005141#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005142#else /* no TPROXY support */
5143 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005144 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005145 err_code |= ERR_ALERT | ERR_FATAL;
5146 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005147#endif
5148 cur_arg += 2;
5149 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005150 }
5151
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005152 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5153#ifdef SO_BINDTODEVICE
5154 if (!*args[cur_arg + 1]) {
5155 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5156 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005159 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005160 free(curproxy->conn_src.iface_name);
5161 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5162 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005163 global.last_checks |= LSTCHK_NETADM;
5164#else
5165 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5166 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005169#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005170 cur_arg += 2;
5171 continue;
5172 }
5173 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005174 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005179 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5180 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5181 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005184 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005186 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5188 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192
5193 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005194 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005195 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005196 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 }
5199 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005201 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005202 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005203 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 }
5206 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005207 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005208 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005209 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005210 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005212 }
5213 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005214 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005215 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005216 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005217 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005219 }
5220 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005221 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005222 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005223 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005224 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005226 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005227 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005229 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005230 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005231 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005232 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005233 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005234 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005235 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005236 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005237 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005238 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005239 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005240 }
5241 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005243 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005244 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005245 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005246 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5251 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005252 err_code |= ERR_ALERT | ERR_FATAL;
5253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005255
5256 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005257 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005258 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005259 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 }
5262 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005264 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005265 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 }
5269 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005271 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005272 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005273 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 }
5276 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005278 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005279 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005280 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 }
5283 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005285 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005286 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005287 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005290 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005292 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005293 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005295 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005298 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005299
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 if (curproxy == &defproxy) {
5301 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005305 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005306 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 if (*(args[1]) == 0) {
5309 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005313
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005314 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005315 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5316 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5317 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005318 err_code |= ERR_ALERT | ERR_FATAL;
5319 goto out;
5320 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005321 err_code |= warnif_cond_conflicts(cond,
5322 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5323 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005324 }
5325 else if (*args[2]) {
5326 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5327 file, linenum, args[0], args[2]);
5328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
5330 }
5331
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005332 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005333 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005334 wl->s = strdup(args[1]);
5335 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005336 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 }
5338 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005339 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5341 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005345
Willy Tarreauade5ec42010-01-28 19:33:49 +01005346 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005347 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005348 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005349 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 }
5352 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005354 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005355 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 }
5359 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005361 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 }
5366 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005367 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5369 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 }
5373
Willy Tarreauade5ec42010-01-28 19:33:49 +01005374 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005375 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005376 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005377 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 }
5380 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005381 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005382 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005383 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005384 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 }
5387 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005388 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005389 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005390 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005391 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 }
5394 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005395 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005396
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397 if (curproxy == &defproxy) {
5398 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005402 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005403 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005404
Willy Tarreaubaaee002006-06-26 02:48:02 +02005405 if (*(args[1]) == 0) {
5406 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005409 }
5410
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005411 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005412 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5413 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5414 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005415 err_code |= ERR_ALERT | ERR_FATAL;
5416 goto out;
5417 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005418 err_code |= warnif_cond_conflicts(cond,
5419 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5420 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005421 }
5422 else if (*args[2]) {
5423 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5424 file, linenum, args[0], args[2]);
5425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
5428
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005429 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005430 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005431 wl->s = strdup(args[1]);
5432 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 }
5434 else if (!strcmp(args[0], "errorloc") ||
5435 !strcmp(args[0], "errorloc302") ||
5436 !strcmp(args[0], "errorloc303")) { /* error location */
5437 int errnum, errlen;
5438 char *err;
5439
Willy Tarreau977b8e42006-12-29 14:19:17 +01005440 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005441 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005442
Willy Tarreaubaaee002006-06-26 02:48:02 +02005443 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005444 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005447 }
5448
5449 errnum = atol(args[1]);
5450 if (!strcmp(args[0], "errorloc303")) {
5451 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5452 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5453 } else {
5454 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5455 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5456 }
5457
Willy Tarreau0f772532006-12-23 20:51:41 +01005458 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5459 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005460 chunk_destroy(&curproxy->errmsg[rc]);
5461 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005462 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005465
5466 if (rc >= HTTP_ERR_SIZE) {
5467 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5468 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 free(err);
5470 }
5471 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005472 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5473 int errnum, errlen, fd;
5474 char *err;
5475 struct stat stat;
5476
5477 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005478 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005479
5480 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005481 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005484 }
5485
5486 fd = open(args[2], O_RDONLY);
5487 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5488 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5489 file, linenum, args[2], args[1]);
5490 if (fd >= 0)
5491 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005494 }
5495
Willy Tarreau27a674e2009-08-17 07:23:33 +02005496 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005497 errlen = stat.st_size;
5498 } else {
5499 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005500 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005501 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005502 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005503 }
5504
5505 err = malloc(errlen); /* malloc() must succeed during parsing */
5506 errnum = read(fd, err, errlen);
5507 if (errnum != errlen) {
5508 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5509 file, linenum, args[2], args[1]);
5510 close(fd);
5511 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005514 }
5515 close(fd);
5516
5517 errnum = atol(args[1]);
5518 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5519 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005520 chunk_destroy(&curproxy->errmsg[rc]);
5521 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005522 break;
5523 }
5524 }
5525
5526 if (rc >= HTTP_ERR_SIZE) {
5527 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5528 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005529 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005530 free(err);
5531 }
5532 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005533 else if (!strcmp(args[0], "compression")) {
5534 struct comp *comp;
5535 if (curproxy->comp == NULL) {
5536 comp = calloc(1, sizeof(struct comp));
5537 curproxy->comp = comp;
5538 } else {
5539 comp = curproxy->comp;
5540 }
5541
5542 if (!strcmp(args[1], "algo")) {
5543 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005544 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005545
William Lallemand82fe75c2012-10-23 10:25:10 +02005546 cur_arg = 2;
5547 if (!*args[cur_arg]) {
5548 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5549 file, linenum, args[0]);
5550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
5552 }
5553 while (*(args[cur_arg])) {
5554 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5555 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5556 file, linenum, args[0], args[cur_arg]);
5557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
5559 }
William Lallemand552df672012-11-07 13:21:47 +01005560 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5561 curproxy->comp->algos->end(&ctx);
5562 } else {
5563 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5564 file, linenum, args[0], args[cur_arg]);
5565 err_code |= ERR_ALERT | ERR_FATAL;
5566 goto out;
5567 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005568 cur_arg ++;
5569 continue;
5570 }
5571 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005572 else if (!strcmp(args[1], "offload")) {
5573 comp->offload = 1;
5574 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005575 else if (!strcmp(args[1], "type")) {
5576 int cur_arg;
5577 cur_arg = 2;
5578 if (!*args[cur_arg]) {
5579 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5580 file, linenum, args[0]);
5581 err_code |= ERR_ALERT | ERR_FATAL;
5582 goto out;
5583 }
5584 while (*(args[cur_arg])) {
5585 comp_append_type(comp, args[cur_arg]);
5586 cur_arg ++;
5587 continue;
5588 }
5589 }
5590 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005591 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005592 file, linenum, args[0]);
5593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
5595 }
5596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005598 struct cfg_kw_list *kwl;
5599 int index;
5600
5601 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5602 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5603 if (kwl->kw[index].section != CFG_LISTEN)
5604 continue;
5605 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5606 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005607 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005608 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005609 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005612 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005613 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005614 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005615 err_code |= ERR_WARN;
5616 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005617 }
Willy Tarreau93893792009-07-23 13:19:11 +02005618 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005619 }
5620 }
5621 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005622
Willy Tarreau6daf3432008-01-22 16:44:08 +01005623 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005624 err_code |= ERR_ALERT | ERR_FATAL;
5625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005626 }
Willy Tarreau93893792009-07-23 13:19:11 +02005627 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005628 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005629 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005630}
5631
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005632int
5633cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5634{
5635
5636 int err_code = 0;
5637 const char *err;
5638
5639 if (!strcmp(args[0], "userlist")) { /* new userlist */
5640 struct userlist *newul;
5641
5642 if (!*args[1]) {
5643 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5644 file, linenum, args[0]);
5645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
5647 }
5648
5649 err = invalid_char(args[1]);
5650 if (err) {
5651 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5652 file, linenum, *err, args[0], args[1]);
5653 err_code |= ERR_ALERT | ERR_FATAL;
5654 goto out;
5655 }
5656
5657 for (newul = userlist; newul; newul = newul->next)
5658 if (!strcmp(newul->name, args[1])) {
5659 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5660 file, linenum, args[1]);
5661 err_code |= ERR_WARN;
5662 goto out;
5663 }
5664
5665 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5666 if (!newul) {
5667 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5668 err_code |= ERR_ALERT | ERR_ABORT;
5669 goto out;
5670 }
5671
5672 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5673 newul->name = strdup(args[1]);
5674
5675 if (!newul->groupusers | !newul->name) {
5676 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5677 err_code |= ERR_ALERT | ERR_ABORT;
5678 goto out;
5679 }
5680
5681 newul->next = userlist;
5682 userlist = newul;
5683
5684 } else if (!strcmp(args[0], "group")) { /* new group */
5685 int cur_arg, i;
5686 const char *err;
5687
5688 if (!*args[1]) {
5689 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5690 file, linenum, args[0]);
5691 err_code |= ERR_ALERT | ERR_FATAL;
5692 goto out;
5693 }
5694
5695 err = invalid_char(args[1]);
5696 if (err) {
5697 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5698 file, linenum, *err, args[0], args[1]);
5699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
5701 }
5702
5703 for(i = 0; i < userlist->grpcnt; i++)
5704 if (!strcmp(userlist->groups[i], args[1])) {
5705 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5706 file, linenum, args[1], userlist->name);
5707 err_code |= ERR_ALERT;
5708 goto out;
5709 }
5710
5711 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5712 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5713 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5714 err_code |= ERR_ALERT | ERR_FATAL;
5715 goto out;
5716 }
5717
5718 cur_arg = 2;
5719
5720 while (*args[cur_arg]) {
5721 if (!strcmp(args[cur_arg], "users")) {
5722 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5723 cur_arg += 2;
5724 continue;
5725 } else {
5726 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5727 file, linenum, args[0]);
5728 err_code |= ERR_ALERT | ERR_FATAL;
5729 goto out;
5730 }
5731 }
5732
5733 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5734 } else if (!strcmp(args[0], "user")) { /* new user */
5735 struct auth_users *newuser;
5736 int cur_arg;
5737
5738 if (!*args[1]) {
5739 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5740 file, linenum, args[0]);
5741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
5743 }
5744
5745 for (newuser = userlist->users; newuser; newuser = newuser->next)
5746 if (!strcmp(newuser->user, args[1])) {
5747 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5748 file, linenum, args[1], userlist->name);
5749 err_code |= ERR_ALERT;
5750 goto out;
5751 }
5752
5753 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5754 if (!newuser) {
5755 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5756 err_code |= ERR_ALERT | ERR_ABORT;
5757 goto out;
5758 }
5759
5760 newuser->user = strdup(args[1]);
5761
5762 newuser->next = userlist->users;
5763 userlist->users = newuser;
5764
5765 cur_arg = 2;
5766
5767 while (*args[cur_arg]) {
5768 if (!strcmp(args[cur_arg], "password")) {
5769#ifndef CONFIG_HAP_CRYPT
5770 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5771 file, linenum);
5772 err_code |= ERR_ALERT;
5773#endif
5774 newuser->pass = strdup(args[cur_arg + 1]);
5775 cur_arg += 2;
5776 continue;
5777 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5778 newuser->pass = strdup(args[cur_arg + 1]);
5779 newuser->flags |= AU_O_INSECURE;
5780 cur_arg += 2;
5781 continue;
5782 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005783 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005784 cur_arg += 2;
5785 continue;
5786 } else {
5787 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5788 file, linenum, args[0]);
5789 err_code |= ERR_ALERT | ERR_FATAL;
5790 goto out;
5791 }
5792 }
5793 } else {
5794 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5795 err_code |= ERR_ALERT | ERR_FATAL;
5796 }
5797
5798out:
5799 return err_code;
5800}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801
5802/*
5803 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005804 * Returns the error code, 0 if OK, or any combination of :
5805 * - ERR_ABORT: must abort ASAP
5806 * - ERR_FATAL: we can continue parsing but not start the service
5807 * - ERR_WARN: a warning has been emitted
5808 * - ERR_ALERT: an alert has been emitted
5809 * Only the two first ones can stop processing, the two others are just
5810 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005812int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005813{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005814 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005815 FILE *f;
5816 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005818 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 if ((f=fopen(file,"r")) == NULL)
5821 return -1;
5822
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005823 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005824 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005825 char *end;
5826 char *args[MAX_LINE_ARGS + 1];
5827 char *line = thisline;
5828
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 linenum++;
5830
5831 end = line + strlen(line);
5832
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005833 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5834 /* Check if we reached the limit and the last char is not \n.
5835 * Watch out for the last line without the terminating '\n'!
5836 */
5837 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005838 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005839 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005840 }
5841
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005843 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005844 line++;
5845
5846 arg = 0;
5847 args[arg] = line;
5848
5849 while (*line && arg < MAX_LINE_ARGS) {
5850 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5851 * C equivalent value. Other combinations left unchanged (eg: \1).
5852 */
5853 if (*line == '\\') {
5854 int skip = 0;
5855 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5856 *line = line[1];
5857 skip = 1;
5858 }
5859 else if (line[1] == 'r') {
5860 *line = '\r';
5861 skip = 1;
5862 }
5863 else if (line[1] == 'n') {
5864 *line = '\n';
5865 skip = 1;
5866 }
5867 else if (line[1] == 't') {
5868 *line = '\t';
5869 skip = 1;
5870 }
5871 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005872 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 unsigned char hex1, hex2;
5874 hex1 = toupper(line[2]) - '0';
5875 hex2 = toupper(line[3]) - '0';
5876 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5877 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5878 *line = (hex1<<4) + hex2;
5879 skip = 3;
5880 }
5881 else {
5882 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005883 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 }
5885 }
5886 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005887 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 end -= skip;
5889 }
5890 line++;
5891 }
5892 else if (*line == '#' || *line == '\n' || *line == '\r') {
5893 /* end of string, end of loop */
5894 *line = 0;
5895 break;
5896 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005897 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005898 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005899 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005900 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 line++;
5902 args[++arg] = line;
5903 }
5904 else {
5905 line++;
5906 }
5907 }
5908
5909 /* empty line */
5910 if (!**args)
5911 continue;
5912
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005913 if (*line) {
5914 /* we had to stop due to too many args.
5915 * Let's terminate the string, print the offending part then cut the
5916 * last arg.
5917 */
5918 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5919 line++;
5920 *line = '\0';
5921
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005922 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005923 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005924 err_code |= ERR_ALERT | ERR_FATAL;
5925 args[arg] = line;
5926 }
5927
Willy Tarreau540abe42007-05-02 20:50:16 +02005928 /* zero out remaining args and ensure that at least one entry
5929 * is zeroed out.
5930 */
5931 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005932 args[arg] = line;
5933 }
5934
Willy Tarreau3842f002009-06-14 11:39:52 +02005935 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005936 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005937 char *tmp;
5938
Willy Tarreau3842f002009-06-14 11:39:52 +02005939 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005940 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005941 for (arg=0; *args[arg+1]; arg++)
5942 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005943 *tmp = '\0'; // fix the next arg to \0
5944 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005945 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005946 else if (!strcmp(args[0], "default")) {
5947 kwm = KWM_DEF;
5948 for (arg=0; *args[arg+1]; arg++)
5949 args[arg] = args[arg+1]; // shift args after inversion
5950 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005951
William Lallemand0f99e342011-10-12 17:50:54 +02005952 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5953 strcmp(args[0], "log") != 0) {
5954 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005955 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005956 }
5957
Willy Tarreau977b8e42006-12-29 14:19:17 +01005958 if (!strcmp(args[0], "listen") ||
5959 !strcmp(args[0], "frontend") ||
5960 !strcmp(args[0], "backend") ||
5961 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005962 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005963 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005964 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005965 cursection = strdup(args[0]);
5966 }
5967 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005968 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005969 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005970 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005971 }
5972 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005973 confsect = CFG_USERLIST;
5974 free(cursection);
5975 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005976 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005977 else if (!strcmp(args[0], "peers")) {
5978 confsect = CFG_PEERS;
5979 free(cursection);
5980 cursection = strdup(args[0]);
5981 }
5982
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983 /* else it's a section keyword */
5984
5985 switch (confsect) {
5986 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005987 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988 break;
5989 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005990 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005992 case CFG_USERLIST:
5993 err_code |= cfg_parse_users(file, linenum, args, kwm);
5994 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005995 case CFG_PEERS:
5996 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5997 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005998 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005999 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006000 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006001 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006002
6003 if (err_code & ERR_ABORT)
6004 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006005 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006006 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006007 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006008 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006009 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006010}
6011
Willy Tarreaubb925012009-07-23 13:36:36 +02006012/*
6013 * Returns the error code, 0 if OK, or any combination of :
6014 * - ERR_ABORT: must abort ASAP
6015 * - ERR_FATAL: we can continue parsing but not start the service
6016 * - ERR_WARN: a warning has been emitted
6017 * - ERR_ALERT: an alert has been emitted
6018 * Only the two first ones can stop processing, the two others are just
6019 * indicators.
6020 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006021int check_config_validity()
6022{
6023 int cfgerr = 0;
6024 struct proxy *curproxy = NULL;
6025 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006026 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006027 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006028 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006029 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006030
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006031 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006032 /*
6033 * Now, check for the integrity of all that we have collected.
6034 */
6035
6036 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006037 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006038
Willy Tarreau193b8c62012-11-22 00:17:38 +01006039 if (!global.tune.max_http_hdr)
6040 global.tune.max_http_hdr = MAX_HTTP_HDR;
6041
6042 if (!global.tune.cookie_len)
6043 global.tune.cookie_len = CAPTURE_LEN;
6044
6045 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6046
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006047 /* first, we will invert the proxy list order */
6048 curproxy = NULL;
6049 while (proxy) {
6050 struct proxy *next;
6051
6052 next = proxy->next;
6053 proxy->next = curproxy;
6054 curproxy = proxy;
6055 if (!next)
6056 break;
6057 proxy = next;
6058 }
6059
Willy Tarreaubaaee002006-06-26 02:48:02 +02006060 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006061 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006062 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006063 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006064 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006065 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006066 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006067 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006068
Willy Tarreau050536d2012-10-04 08:47:34 +02006069 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006070 /* proxy ID not set, use automatic numbering with first
6071 * spare entry starting with next_pxid.
6072 */
6073 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6074 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6075 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006076 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006077 next_pxid++;
6078
Willy Tarreau55ea7572007-06-17 19:56:27 +02006079
Willy Tarreaubaaee002006-06-26 02:48:02 +02006080 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006081 /* ensure we don't keep listeners uselessly bound */
6082 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006083 curproxy = curproxy->next;
6084 continue;
6085 }
6086
Willy Tarreau16a21472012-11-19 12:39:59 +01006087 /* number of processes this proxy is bound to */
6088 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6089
Willy Tarreauff01a212009-03-15 13:46:16 +01006090 switch (curproxy->mode) {
6091 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006092 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006093 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006094 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6095 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006096 cfgerr++;
6097 }
6098
6099 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006100 Warning("config : servers will be ignored for %s '%s'.\n",
6101 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006102 break;
6103
6104 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006105 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006106 break;
6107
6108 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006109 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006110 break;
6111 }
6112
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006113 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006114 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006115 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006116 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6117 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006118 cfgerr++;
6119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006120#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006121 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006122 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6123 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006124 cfgerr++;
6125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006126#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006127 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006128 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6129 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006130 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006131 }
6132 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006133 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006134 /* If no LB algo is set in a backend, and we're not in
6135 * transparent mode, dispatch mode nor proxy mode, we
6136 * want to use balance roundrobin by default.
6137 */
6138 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6139 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006140 }
6141 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006142
Willy Tarreau1620ec32011-08-06 17:05:02 +02006143 if (curproxy->options & PR_O_DISPATCH)
6144 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6145 else if (curproxy->options & PR_O_HTTP_PROXY)
6146 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6147 else if (curproxy->options & PR_O_TRANSP)
6148 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006149
Willy Tarreau1620ec32011-08-06 17:05:02 +02006150 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6151 if (curproxy->options & PR_O_DISABLE404) {
6152 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6153 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6154 err_code |= ERR_WARN;
6155 curproxy->options &= ~PR_O_DISABLE404;
6156 }
6157 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6158 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6159 "send-state", proxy_type_str(curproxy), curproxy->id);
6160 err_code |= ERR_WARN;
6161 curproxy->options &= ~PR_O2_CHK_SNDST;
6162 }
Willy Tarreauef781042010-01-27 11:53:01 +01006163 }
6164
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006165 /* if a default backend was specified, let's find it */
6166 if (curproxy->defbe.name) {
6167 struct proxy *target;
6168
Alex Williams96532db2009-11-01 21:27:13 -05006169 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006170 if (!target) {
6171 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6172 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006173 cfgerr++;
6174 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006175 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6176 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006177 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006178 } else {
6179 free(curproxy->defbe.name);
6180 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006181 /* we force the backend to be present on at least all of
6182 * the frontend's processes.
6183 */
6184 target->bind_proc = curproxy->bind_proc ?
6185 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006186
6187 /* Emit a warning if this proxy also has some servers */
6188 if (curproxy->srv) {
6189 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6190 curproxy->id);
6191 err_code |= ERR_WARN;
6192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193 }
6194 }
6195
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006196 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006197 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6198 /* map jump target for ACT_SETBE in req_rep chain */
6199 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006200 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006201 struct proxy *target;
6202
Willy Tarreaua496b602006-12-17 23:15:24 +01006203 if (exp->action != ACT_SETBE)
6204 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006205
Alex Williams96532db2009-11-01 21:27:13 -05006206 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006207 if (!target) {
6208 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6209 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006210 cfgerr++;
6211 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006212 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6213 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006214 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006215 } else {
6216 free((void *)exp->replace);
6217 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006218 /* we force the backend to be present on at least all of
6219 * the frontend's processes.
6220 */
6221 target->bind_proc = curproxy->bind_proc ?
6222 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006223 }
6224 }
6225 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006226
6227 /* find the target proxy for 'use_backend' rules */
6228 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006229 struct proxy *target;
6230
Alex Williams96532db2009-11-01 21:27:13 -05006231 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006232
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006233 if (!target) {
6234 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6235 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006236 cfgerr++;
6237 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006238 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6239 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006240 cfgerr++;
6241 } else {
6242 free((void *)rule->be.name);
6243 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006244 /* we force the backend to be present on at least all of
6245 * the frontend's processes.
6246 */
6247 target->bind_proc = curproxy->bind_proc ?
6248 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006249 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006250 }
6251
6252 /* find the target proxy for 'use_backend' rules */
6253 list_for_each_entry(srule, &curproxy->server_rules, list) {
6254 struct server *target = findserver(curproxy, srule->srv.name);
6255
6256 if (!target) {
6257 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6258 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6259 cfgerr++;
6260 continue;
6261 }
6262 free((void *)srule->srv.name);
6263 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006264 }
6265
Emeric Brunb982a3d2010-01-04 15:45:53 +01006266 /* find the target table for 'stick' rules */
6267 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6268 struct proxy *target;
6269
Emeric Brun1d33b292010-01-04 15:47:17 +01006270 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6271 if (mrule->flags & STK_IS_STORE)
6272 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6273
Emeric Brunb982a3d2010-01-04 15:45:53 +01006274 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006275 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006276 else
6277 target = curproxy;
6278
6279 if (!target) {
6280 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6281 curproxy->id, mrule->table.name);
6282 cfgerr++;
6283 }
6284 else if (target->table.size == 0) {
6285 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6286 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6287 cfgerr++;
6288 }
Willy Tarreau12785782012-04-27 21:37:17 +02006289 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6290 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006291 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6292 cfgerr++;
6293 }
6294 else {
6295 free((void *)mrule->table.name);
6296 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006297 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006298 }
6299 }
6300
6301 /* find the target table for 'store response' rules */
6302 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6303 struct proxy *target;
6304
Emeric Brun1d33b292010-01-04 15:47:17 +01006305 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6306
Emeric Brunb982a3d2010-01-04 15:45:53 +01006307 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006308 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006309 else
6310 target = curproxy;
6311
6312 if (!target) {
6313 Alert("Proxy '%s': unable to find store table '%s'.\n",
6314 curproxy->id, mrule->table.name);
6315 cfgerr++;
6316 }
6317 else if (target->table.size == 0) {
6318 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6319 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6320 cfgerr++;
6321 }
Willy Tarreau12785782012-04-27 21:37:17 +02006322 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6323 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006324 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6325 cfgerr++;
6326 }
6327 else {
6328 free((void *)mrule->table.name);
6329 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006330 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006331 }
6332 }
6333
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006334 /* find the target table for 'tcp-request' layer 4 rules */
6335 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6336 struct proxy *target;
6337
Willy Tarreaue25c9172013-05-28 18:32:20 +02006338 if (trule->action < TCP_ACT_TRK_SC1 || trule->action > TCP_ACT_TRK_SC3)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006339 continue;
6340
6341 if (trule->act_prm.trk_ctr.table.n)
6342 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6343 else
6344 target = curproxy;
6345
6346 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006347 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6348 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006349 1 + tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006350 cfgerr++;
6351 }
6352 else if (target->table.size == 0) {
6353 Alert("Proxy '%s': table '%s' used but not configured.\n",
6354 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6355 cfgerr++;
6356 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006357 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6358 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6359 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006360 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006361 cfgerr++;
6362 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006363 else {
6364 free(trule->act_prm.trk_ctr.table.n);
6365 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006366 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006367 * to pass a list of counters to track and allocate them right here using
6368 * stktable_alloc_data_type().
6369 */
6370 }
6371 }
6372
Willy Tarreaud1f96522010-08-03 19:34:32 +02006373 /* find the target table for 'tcp-request' layer 6 rules */
6374 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6375 struct proxy *target;
6376
Willy Tarreaue25c9172013-05-28 18:32:20 +02006377 if (trule->action < TCP_ACT_TRK_SC1 || trule->action > TCP_ACT_TRK_SC3)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006378 continue;
6379
6380 if (trule->act_prm.trk_ctr.table.n)
6381 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6382 else
6383 target = curproxy;
6384
6385 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006386 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6387 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006388 1 + tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006389 cfgerr++;
6390 }
6391 else if (target->table.size == 0) {
6392 Alert("Proxy '%s': table '%s' used but not configured.\n",
6393 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6394 cfgerr++;
6395 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006396 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6397 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6398 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006399 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006400 cfgerr++;
6401 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006402 else {
6403 free(trule->act_prm.trk_ctr.table.n);
6404 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006405 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006406 * to pass a list of counters to track and allocate them right here using
6407 * stktable_alloc_data_type().
6408 */
6409 }
6410 }
6411
Emeric Brun32da3c42010-09-23 18:39:19 +02006412 if (curproxy->table.peers.name) {
6413 struct peers *curpeers = peers;
6414
6415 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6416 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6417 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006418 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006419 break;
6420 }
6421 }
6422
6423 if (!curpeers) {
6424 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6425 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006426 free((void *)curproxy->table.peers.name);
6427 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006428 cfgerr++;
6429 }
6430 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006431 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6432 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006433 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006434 cfgerr++;
6435 }
6436 }
6437
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006438 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006439 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006440 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6441 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6442 "proxy", curproxy->id);
6443 cfgerr++;
6444 goto out_uri_auth_compat;
6445 }
6446
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006447 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006448 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006449 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006450 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006451
Willy Tarreau95fa4692010-02-01 13:05:50 +01006452 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6453 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006454
6455 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006456 uri_auth_compat_req[i++] = "realm";
6457 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6458 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006459
Willy Tarreau95fa4692010-02-01 13:05:50 +01006460 uri_auth_compat_req[i++] = "unless";
6461 uri_auth_compat_req[i++] = "{";
6462 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6463 uri_auth_compat_req[i++] = "}";
6464 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006465
Willy Tarreauff011f22011-01-06 17:51:27 +01006466 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6467 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006468 cfgerr++;
6469 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006470 }
6471
Willy Tarreauff011f22011-01-06 17:51:27 +01006472 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006473
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006474 if (curproxy->uri_auth->auth_realm) {
6475 free(curproxy->uri_auth->auth_realm);
6476 curproxy->uri_auth->auth_realm = NULL;
6477 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006478
6479 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006480 }
6481out_uri_auth_compat:
6482
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006483 /* compile the log format */
6484 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006485 if (curproxy->conf.logformat_string != default_http_log_format &&
6486 curproxy->conf.logformat_string != default_tcp_log_format &&
6487 curproxy->conf.logformat_string != clf_http_log_format)
6488 free(curproxy->conf.logformat_string);
6489 curproxy->conf.logformat_string = NULL;
6490 free(curproxy->conf.lfs_file);
6491 curproxy->conf.lfs_file = NULL;
6492 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006493 }
6494
Willy Tarreau62a61232013-04-12 18:13:46 +02006495 if (curproxy->conf.logformat_string) {
6496 curproxy->conf.args.ctx = ARGC_LOG;
6497 curproxy->conf.args.file = curproxy->conf.lfs_file;
6498 curproxy->conf.args.line = curproxy->conf.lfs_line;
6499 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006500 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006501 curproxy->conf.args.file = NULL;
6502 curproxy->conf.args.line = 0;
6503 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006504
Willy Tarreau62a61232013-04-12 18:13:46 +02006505 if (curproxy->conf.uniqueid_format_string) {
6506 curproxy->conf.args.ctx = ARGC_UIF;
6507 curproxy->conf.args.file = curproxy->conf.uif_file;
6508 curproxy->conf.args.line = curproxy->conf.uif_line;
6509 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006510 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006511 curproxy->conf.args.file = NULL;
6512 curproxy->conf.args.line = 0;
6513 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006514
6515 /* only now we can check if some args remain unresolved */
6516 cfgerr += smp_resolve_args(curproxy);
6517 if (!cfgerr)
6518 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006519
Willy Tarreau2738a142006-07-08 17:28:09 +02006520 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006521 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006522 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006523 (!curproxy->timeout.connect ||
6524 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006525 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006526 " | While not properly invalid, you will certainly encounter various problems\n"
6527 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006528 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006529 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006530 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006531 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006532
Willy Tarreau1fa31262007-12-03 00:36:16 +01006533 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6534 * We must still support older configurations, so let's find out whether those
6535 * parameters have been set or must be copied from contimeouts.
6536 */
6537 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006538 if (!curproxy->timeout.tarpit ||
6539 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006540 /* tarpit timeout not set. We search in the following order:
6541 * default.tarpit, curr.connect, default.connect.
6542 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006543 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006544 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006545 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006546 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006547 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006548 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006549 }
6550 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006551 (!curproxy->timeout.queue ||
6552 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006553 /* queue timeout not set. We search in the following order:
6554 * default.queue, curr.connect, default.connect.
6555 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006556 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006557 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006558 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006559 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006560 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006561 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006562 }
6563 }
6564
Willy Tarreau1620ec32011-08-06 17:05:02 +02006565 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006566 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6567 curproxy->check_req = (char *)malloc(curproxy->check_len);
6568 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006569 }
6570
Willy Tarreau193b8c62012-11-22 00:17:38 +01006571 /* ensure that cookie capture length is not too large */
6572 if (curproxy->capture_len >= global.tune.cookie_len) {
6573 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6574 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6575 err_code |= ERR_WARN;
6576 curproxy->capture_len = global.tune.cookie_len - 1;
6577 }
6578
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006579 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006580 if (curproxy->nb_req_cap) {
6581 if (curproxy->mode == PR_MODE_HTTP) {
6582 curproxy->req_cap_pool = create_pool("ptrcap",
6583 curproxy->nb_req_cap * sizeof(char *),
6584 MEM_F_SHARED);
6585 } else {
6586 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6587 proxy_type_str(curproxy), curproxy->id);
6588 err_code |= ERR_WARN;
6589 curproxy->to_log &= ~LW_REQHDR;
6590 curproxy->nb_req_cap = 0;
6591 }
6592 }
6593
6594 if (curproxy->nb_rsp_cap) {
6595 if (curproxy->mode == PR_MODE_HTTP) {
6596 curproxy->rsp_cap_pool = create_pool("ptrcap",
6597 curproxy->nb_rsp_cap * sizeof(char *),
6598 MEM_F_SHARED);
6599 } else {
6600 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6601 proxy_type_str(curproxy), curproxy->id);
6602 err_code |= ERR_WARN;
6603 curproxy->to_log &= ~LW_REQHDR;
6604 curproxy->nb_rsp_cap = 0;
6605 }
6606 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006607
Willy Tarreaubaaee002006-06-26 02:48:02 +02006608 /* first, we will invert the servers list order */
6609 newsrv = NULL;
6610 while (curproxy->srv) {
6611 struct server *next;
6612
6613 next = curproxy->srv->next;
6614 curproxy->srv->next = newsrv;
6615 newsrv = curproxy->srv;
6616 if (!next)
6617 break;
6618 curproxy->srv = next;
6619 }
6620
Willy Tarreaudd701652010-05-25 23:03:02 +02006621 /* assign automatic UIDs to servers which don't have one yet */
6622 next_id = 1;
6623 newsrv = curproxy->srv;
6624 while (newsrv != NULL) {
6625 if (!newsrv->puid) {
6626 /* server ID not set, use automatic numbering with first
6627 * spare entry starting with next_svid.
6628 */
6629 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6630 newsrv->conf.id.key = newsrv->puid = next_id;
6631 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6632 }
6633 next_id++;
6634 newsrv = newsrv->next;
6635 }
6636
Willy Tarreau20697042007-11-15 23:26:18 +01006637 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006638 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006639
Willy Tarreau62c3be22012-01-20 13:12:32 +01006640 /*
6641 * If this server supports a maxconn parameter, it needs a dedicated
6642 * tasks to fill the emptied slots when a connection leaves.
6643 * Also, resolve deferred tracking dependency if needed.
6644 */
6645 newsrv = curproxy->srv;
6646 while (newsrv != NULL) {
6647 if (newsrv->minconn > newsrv->maxconn) {
6648 /* Only 'minconn' was specified, or it was higher than or equal
6649 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6650 * this will avoid further useless expensive computations.
6651 */
6652 newsrv->maxconn = newsrv->minconn;
6653 } else if (newsrv->maxconn && !newsrv->minconn) {
6654 /* minconn was not specified, so we set it to maxconn */
6655 newsrv->minconn = newsrv->maxconn;
6656 }
6657
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006658#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006659 if (newsrv->use_ssl || newsrv->check.use_ssl)
6660 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006661#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006662
Willy Tarreau62c3be22012-01-20 13:12:32 +01006663 if (newsrv->trackit) {
6664 struct proxy *px;
6665 struct server *srv;
6666 char *pname, *sname;
6667
6668 pname = newsrv->trackit;
6669 sname = strrchr(pname, '/');
6670
6671 if (sname)
6672 *sname++ = '\0';
6673 else {
6674 sname = pname;
6675 pname = NULL;
6676 }
6677
6678 if (pname) {
6679 px = findproxy(pname, PR_CAP_BE);
6680 if (!px) {
6681 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6682 proxy_type_str(curproxy), curproxy->id,
6683 newsrv->id, pname);
6684 cfgerr++;
6685 goto next_srv;
6686 }
6687 } else
6688 px = curproxy;
6689
6690 srv = findserver(px, sname);
6691 if (!srv) {
6692 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6693 proxy_type_str(curproxy), curproxy->id,
6694 newsrv->id, sname);
6695 cfgerr++;
6696 goto next_srv;
6697 }
6698
6699 if (!(srv->state & SRV_CHECKED)) {
6700 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6701 "tracking as it does not have checks enabled.\n",
6702 proxy_type_str(curproxy), curproxy->id,
6703 newsrv->id, px->id, srv->id);
6704 cfgerr++;
6705 goto next_srv;
6706 }
6707
6708 if (curproxy != px &&
6709 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6710 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6711 "tracking: disable-on-404 option inconsistency.\n",
6712 proxy_type_str(curproxy), curproxy->id,
6713 newsrv->id, px->id, srv->id);
6714 cfgerr++;
6715 goto next_srv;
6716 }
6717
6718 /* if the other server is forced disabled, we have to do the same here */
6719 if (srv->state & SRV_MAINTAIN) {
6720 newsrv->state |= SRV_MAINTAIN;
6721 newsrv->state &= ~SRV_RUNNING;
6722 newsrv->health = 0;
6723 }
6724
6725 newsrv->track = srv;
6726 newsrv->tracknext = srv->tracknext;
6727 srv->tracknext = newsrv;
6728
6729 free(newsrv->trackit);
6730 newsrv->trackit = NULL;
6731 }
6732 next_srv:
6733 newsrv = newsrv->next;
6734 }
6735
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006736 /* We have to initialize the server lookup mechanism depending
6737 * on what LB algorithm was choosen.
6738 */
6739
6740 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6741 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6742 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006743 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6744 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6745 init_server_map(curproxy);
6746 } else {
6747 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6748 fwrr_init_server_groups(curproxy);
6749 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006750 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006751
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006752 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006753 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6754 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6755 fwlc_init_server_tree(curproxy);
6756 } else {
6757 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6758 fas_init_server_tree(curproxy);
6759 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006760 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006761
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006762 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006763 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6764 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6765 chash_init_server_tree(curproxy);
6766 } else {
6767 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6768 init_server_map(curproxy);
6769 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006770 break;
6771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006772
6773 if (curproxy->options & PR_O_LOGASAP)
6774 curproxy->to_log &= ~LW_BYTES;
6775
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006776 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006777 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006778 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6779 proxy_type_str(curproxy), curproxy->id);
6780 err_code |= ERR_WARN;
6781 }
6782
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006783 if (curproxy->mode != PR_MODE_HTTP) {
6784 int optnum;
6785
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006786 if (curproxy->uri_auth) {
6787 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6788 proxy_type_str(curproxy), curproxy->id);
6789 err_code |= ERR_WARN;
6790 curproxy->uri_auth = NULL;
6791 }
6792
Willy Tarreau87cf5142011-08-19 22:57:24 +02006793 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006794 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6795 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6796 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006797 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006798 }
6799
6800 if (curproxy->options & PR_O_ORGTO) {
6801 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6802 "originalto", proxy_type_str(curproxy), curproxy->id);
6803 err_code |= ERR_WARN;
6804 curproxy->options &= ~PR_O_ORGTO;
6805 }
6806
6807 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6808 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6809 (curproxy->cap & cfg_opts[optnum].cap) &&
6810 (curproxy->options & cfg_opts[optnum].val)) {
6811 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6812 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6813 err_code |= ERR_WARN;
6814 curproxy->options &= ~cfg_opts[optnum].val;
6815 }
6816 }
6817
6818 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6819 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6820 (curproxy->cap & cfg_opts2[optnum].cap) &&
6821 (curproxy->options2 & cfg_opts2[optnum].val)) {
6822 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6823 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6824 err_code |= ERR_WARN;
6825 curproxy->options2 &= ~cfg_opts2[optnum].val;
6826 }
6827 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006828
Pieter Baauwd551fb52013-05-08 22:49:23 +02006829#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006830 if (curproxy->conn_src.bind_hdr_occ) {
6831 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006832 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006833 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006834 err_code |= ERR_WARN;
6835 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006836#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006837 }
6838
Willy Tarreaubaaee002006-06-26 02:48:02 +02006839 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006840 * ensure that we're not cross-dressing a TCP server into HTTP.
6841 */
6842 newsrv = curproxy->srv;
6843 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006844 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006845 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6846 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006847 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006848 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006849
Willy Tarreau0cec3312011-10-31 13:49:26 +01006850 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6851 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6852 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6853 err_code |= ERR_WARN;
6854 }
6855
Pieter Baauwd551fb52013-05-08 22:49:23 +02006856#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006857 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6858 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006859 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 +01006860 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006861 err_code |= ERR_WARN;
6862 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006863#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006864 newsrv = newsrv->next;
6865 }
6866
Willy Tarreauc1a21672009-08-16 22:37:44 +02006867 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006868 if (!curproxy->accept)
6869 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006870
Willy Tarreauc1a21672009-08-16 22:37:44 +02006871 if (curproxy->tcp_req.inspect_delay ||
6872 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006873 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006874
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006875 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006876 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006877 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006878 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006879
6880 /* both TCP and HTTP must check switching rules */
6881 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6882 }
6883
6884 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006885 if (curproxy->tcp_req.inspect_delay ||
6886 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6887 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6888
Emeric Brun97679e72010-09-23 17:56:44 +02006889 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6890 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6891
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006892 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006893 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006894 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006895 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006896
6897 /* If the backend does requires RDP cookie persistence, we have to
6898 * enable the corresponding analyser.
6899 */
6900 if (curproxy->options2 & PR_O2_RDPC_PRST)
6901 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6902 }
6903
Emeric Brunc52962f2012-11-15 18:28:02 +01006904#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006905 /* Configure SSL for each bind line.
6906 * Note: if configuration fails at some point, the ->ctx member
6907 * remains NULL so that listeners can later detach.
6908 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006909 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006910 if (!bind_conf->is_ssl) {
6911 if (bind_conf->default_ctx) {
6912 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6913 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6914 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006915 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006916 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006917 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006918 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006919 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006920 cfgerr++;
6921 continue;
6922 }
6923
Emeric Brun4b3091e2012-09-24 15:48:52 +02006924 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006925 Alert("Unable to allocate SSL session cache.\n");
6926 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006927 continue;
6928 }
6929
Emeric Brunfc0421f2012-09-07 17:30:07 +02006930 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006931 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006932 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006933#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006934
Willy Tarreaue6b98942007-10-29 01:09:36 +01006935 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006936 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006937 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006938 if (!listener->luid) {
6939 /* listener ID not set, use automatic numbering with first
6940 * spare entry starting with next_luid.
6941 */
6942 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6943 listener->conf.id.key = listener->luid = next_id;
6944 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006945 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006946 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006947
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006948 /* enable separate counters */
6949 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6950 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006951 if (!listener->name)
6952 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006953 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006954
Willy Tarreaue6b98942007-10-29 01:09:36 +01006955 if (curproxy->options & PR_O_TCP_NOLING)
6956 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006957 if (!listener->maxconn)
6958 listener->maxconn = curproxy->maxconn;
6959 if (!listener->backlog)
6960 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006961 if (!listener->maxaccept)
6962 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6963
6964 /* we want to have an optimal behaviour on single process mode to
6965 * maximize the work at once, but in multi-process we want to keep
6966 * some fairness between processes, so we target half of the max
6967 * number of events to be balanced over all the processes the proxy
6968 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6969 * used to disable the limit.
6970 */
6971 if (listener->maxaccept > 0) {
6972 if (nbproc > 1)
6973 listener->maxaccept = (listener->maxaccept + 1) / 2;
6974 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6975 }
6976
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006977 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006978 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006979 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006980 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006981
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006982 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6983 listener->options |= LI_O_TCP_RULES;
6984
Willy Tarreaude3041d2010-05-31 10:56:17 +02006985 if (curproxy->mon_mask.s_addr)
6986 listener->options |= LI_O_CHK_MONNET;
6987
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006988 /* smart accept mode is automatic in HTTP mode */
6989 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006990 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006991 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6992 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006993 }
6994
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006995 /* Release unused SSL configs */
6996 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6997 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006998 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006999#ifdef USE_OPENSSL
7000 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007001 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007002 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007003 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007004 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007005#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007006 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007007
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007008 /* Check multi-process mode compatibility for the current proxy */
7009 if (global.nbproc > 1) {
7010 int nbproc = 0;
7011 if (curproxy->bind_proc) {
7012 int proc;
7013 for (proc = 0; proc < global.nbproc; proc++) {
7014 if (curproxy->bind_proc & (1 << proc)) {
7015 nbproc++;
7016 }
7017 }
7018 } else {
7019 nbproc = global.nbproc;
7020 }
7021 if (curproxy->table.peers.name) {
7022 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7023 curproxy->id);
7024 cfgerr++;
7025 }
7026 if (nbproc > 1) {
7027 if (curproxy->uri_auth) {
7028 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7029 curproxy->id);
7030 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7031 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7032 curproxy->id);
7033 }
7034 }
7035 if (curproxy->appsession_name) {
7036 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7037 curproxy->id);
7038 }
7039 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7040 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7041 curproxy->id);
7042 }
7043 }
7044 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007045
7046 /* create the task associated with the proxy */
7047 curproxy->task = task_new();
7048 if (curproxy->task) {
7049 curproxy->task->context = curproxy;
7050 curproxy->task->process = manage_proxy;
7051 /* no need to queue, it will be done automatically if some
7052 * listener gets limited.
7053 */
7054 curproxy->task->expire = TICK_ETERNITY;
7055 } else {
7056 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7057 curproxy->id);
7058 cfgerr++;
7059 }
7060
Willy Tarreaubaaee002006-06-26 02:48:02 +02007061 curproxy = curproxy->next;
7062 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007063
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007064 /* Check multi-process mode compatibility */
7065 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007066 if (global.stats_fe && !global.stats_fe->bind_proc) {
7067 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 +01007068 }
7069 }
7070
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007071 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7072 struct auth_users *curuser;
7073 int g;
7074
7075 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7076 unsigned int group_mask = 0;
7077 char *group = NULL;
7078
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007079 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007080 continue;
7081
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007082 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007083
7084 for (g = 0; g < curuserlist->grpcnt; g++)
7085 if (!strcmp(curuserlist->groups[g], group))
7086 break;
7087
7088 if (g == curuserlist->grpcnt) {
7089 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7090 curuserlist->name, group, curuser->user);
7091 err_code |= ERR_ALERT | ERR_FATAL;
7092 goto out;
7093 }
7094
7095 group_mask |= (1 << g);
7096 }
7097
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007098 free(curuser->u.groups);
7099 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007100 }
7101
7102 for (g = 0; g < curuserlist->grpcnt; g++) {
7103 char *user = NULL;
7104
7105 if (!curuserlist->groupusers[g])
7106 continue;
7107
7108 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7109 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7110 if (!strcmp(curuser->user, user))
7111 break;
7112
7113 if (!curuser) {
7114 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7115 curuserlist->name, user, curuserlist->groups[g]);
7116 err_code |= ERR_ALERT | ERR_FATAL;
7117 goto out;
7118 }
7119
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007120 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007121 }
7122
7123 free(curuserlist->groupusers[g]);
7124 }
7125
7126 free(curuserlist->groupusers);
7127
7128#ifdef DEBUG_AUTH
7129 for (g = 0; g < curuserlist->grpcnt; g++) {
7130 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7131
7132 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007133 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007134 fprintf(stderr, " %s", curuser->user);
7135 }
7136
7137 fprintf(stderr, "\n");
7138 }
7139#endif
7140
Willy Tarreaufbb78422011-06-05 15:38:35 +02007141 }
7142
7143 /* automatically compute fullconn if not set. We must not do it in the
7144 * loop above because cross-references are not yet fully resolved.
7145 */
7146 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7147 /* If <fullconn> is not set, let's set it to 10% of the sum of
7148 * the possible incoming frontend's maxconns.
7149 */
7150 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7151 struct proxy *fe;
7152 int total = 0;
7153
7154 /* sum up the number of maxconns of frontends which
7155 * reference this backend at least once or which are
7156 * the same one ('listen').
7157 */
7158 for (fe = proxy; fe; fe = fe->next) {
7159 struct switching_rule *rule;
7160 struct hdr_exp *exp;
7161 int found = 0;
7162
7163 if (!(fe->cap & PR_CAP_FE))
7164 continue;
7165
7166 if (fe == curproxy) /* we're on a "listen" instance */
7167 found = 1;
7168
7169 if (fe->defbe.be == curproxy) /* "default_backend" */
7170 found = 1;
7171
7172 /* check if a "use_backend" rule matches */
7173 if (!found) {
7174 list_for_each_entry(rule, &fe->switching_rules, list) {
7175 if (rule->be.backend == curproxy) {
7176 found = 1;
7177 break;
7178 }
7179 }
7180 }
7181
7182 /* check if a "reqsetbe" rule matches */
7183 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7184 if (exp->action == ACT_SETBE &&
7185 (struct proxy *)exp->replace == curproxy) {
7186 found = 1;
7187 break;
7188 }
7189 }
7190
7191 /* now we've checked all possible ways to reference a backend
7192 * from a frontend.
7193 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007194 if (!found)
7195 continue;
7196 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007197 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007198 /* we have the sum of the maxconns in <total>. We only
7199 * keep 10% of that sum to set the default fullconn, with
7200 * a hard minimum of 1 (to avoid a divide by zero).
7201 */
7202 curproxy->fullconn = (total + 9) / 10;
7203 if (!curproxy->fullconn)
7204 curproxy->fullconn = 1;
7205 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007206 }
7207
Willy Tarreau056f5682010-06-06 15:51:11 +02007208 /* initialize stick-tables on backend capable proxies. This must not
7209 * be done earlier because the data size may be discovered while parsing
7210 * other proxies.
7211 */
7212 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007213 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007214
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007215 /*
7216 * Recount currently required checks.
7217 */
7218
7219 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7220 int optnum;
7221
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007222 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7223 if (curproxy->options & cfg_opts[optnum].val)
7224 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007225
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007226 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7227 if (curproxy->options2 & cfg_opts2[optnum].val)
7228 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007229 }
7230
Willy Tarreau122541c2011-09-07 21:24:49 +02007231 if (peers) {
7232 struct peers *curpeers = peers, **last;
7233 struct peer *p, *pb;
7234
7235 /* Remove all peers sections which don't have a valid listener.
7236 * This can happen when a peers section is never referenced and
7237 * does not contain a local peer.
7238 */
7239 last = &peers;
7240 while (*last) {
7241 curpeers = *last;
7242 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007243 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007244 last = &curpeers->next;
7245 continue;
7246 }
7247
7248 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7249 curpeers->id, localpeer);
7250
7251 p = curpeers->remote;
7252 while (p) {
7253 pb = p->next;
7254 free(p->id);
7255 free(p);
7256 p = pb;
7257 }
7258
7259 /* Destroy and unlink this curpeers section.
7260 * Note: curpeers is backed up into *last.
7261 */
7262 free(curpeers->id);
7263 curpeers = curpeers->next;
7264 free(*last);
7265 *last = curpeers;
7266 }
7267 }
7268
Willy Tarreau34eb6712011-10-24 18:15:04 +02007269 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007270 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007271 MEM_F_SHARED);
7272
Willy Tarreaubb925012009-07-23 13:36:36 +02007273 if (cfgerr > 0)
7274 err_code |= ERR_ALERT | ERR_FATAL;
7275 out:
7276 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007277}
7278
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007279/*
7280 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7281 * parsing sessions.
7282 */
7283void cfg_register_keywords(struct cfg_kw_list *kwl)
7284{
7285 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7286}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007287
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007288/*
7289 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7290 */
7291void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7292{
7293 LIST_DEL(&kwl->list);
7294 LIST_INIT(&kwl->list);
7295}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007296
7297/*
7298 * Local variables:
7299 * c-indent-level: 8
7300 * c-basic-offset: 8
7301 * End:
7302 */