blob: 7f521b1a7928787f17b285cc198ae5b5e099b772 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100209 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100210 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
212 str = next;
213 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100214 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 *next++ = 0;
216 }
217
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100218 ss2 = str2sa_range(str, &port, &end, err,
219 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
220 if (!ss2)
221 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100223 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100224 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100229 if (!port || !end) {
230 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
231 goto fail;
232 }
233
Emeric Bruned760922010-10-22 17:59:25 +0200234 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200235 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200236 goto fail;
237 }
238
239 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200240 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 else if (ss2->ss_family == AF_UNSPEC) {
245 socklen_t addr_len;
246
247 /* We want to attach to an already bound fd whose number
248 * is in the addr part of ss2 when cast to sockaddr_in.
249 * Note that by definition there is a single listener.
250 * We still have to determine the address family to
251 * register the correct protocol.
252 */
253 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
254 addr_len = sizeof(*ss2);
255 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
256 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
257 goto fail;
258 }
259
260 port = end = get_host_port(ss2);
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100263 /* OK the address looks correct */
264 ss = *ss2;
265
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100268 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200269 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
270 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
271 l->frontend = curproxy;
272 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273
Willy Tarreau40aa0702013-03-10 23:51:38 +0100274 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200276 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100277 l->state = LI_INIT;
278
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100279 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100281 tcpv4_add_listener(l);
282 }
Emeric Bruned760922010-10-22 17:59:25 +0200283 else if (ss.ss_family == AF_INET6) {
284 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
285 tcpv6_add_listener(l);
286 }
287 else {
Emeric Bruned760922010-10-22 17:59:25 +0200288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100417/* Report it if a request ACL condition uses some keywords that are incompatible
418 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
419 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
420 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100421 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100422static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200425 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100428 return 0;
429
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100430 acl = acl_cond_conflicts(cond, where);
431 if (acl) {
432 if (acl->name && *acl->name)
433 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
434 file, line, acl->name, sample_ckp_names(where));
435 else
436 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200437 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100438 return ERR_WARN;
439 }
440 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100441 return 0;
442
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 if (acl->name && *acl->name)
444 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446 else
447 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200448 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100449 return ERR_WARN;
450}
451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200471 else if (!strcmp(args[0], "ca-base")) {
472#ifdef USE_OPENSSL
473 if (global.ca_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.ca_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
490 else if (!strcmp(args[0], "crt-base")) {
491#ifdef USE_OPENSSL
492 if (global.crt_base != NULL) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.crt_base = strdup(args[1]);
503#else
504 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507#endif
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "daemon")) {
510 global.mode |= MODE_DAEMON;
511 }
512 else if (!strcmp(args[0], "debug")) {
513 global.mode |= MODE_DEBUG;
514 }
515 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200518 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100524 else if (!strcmp(args[0], "nosplice")) {
525 global.tune.options &= ~GTUNE_USE_SPLICE;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "quiet")) {
528 global.mode |= MODE_QUIET;
529 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200530 else if (!strcmp(args[0], "tune.maxpollevents")) {
531 if (global.tune.maxpollevents != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200540 }
541 global.tune.maxpollevents = atol(args[1]);
542 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100543 else if (!strcmp(args[0], "tune.maxaccept")) {
544 if (global.tune.maxaccept != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100553 }
554 global.tune.maxaccept = atol(args[1]);
555 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200556 else if (!strcmp(args[0], "tune.chksize")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.chksize = atol(args[1]);
563 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200564#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100565 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.sslcachesize = atol(args[1]);
572 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100573 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
574 unsigned int ssllifetime;
575 const char *res;
576
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582
583 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
584 if (res) {
585 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
586 file, linenum, *res, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590
591 global.tune.ssllifetime = ssllifetime;
592 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100593 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.ssl_max_record = atol(args[1]);
600 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200602 else if (!strcmp(args[0], "tune.bufsize")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.bufsize = atol(args[1]);
609 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
610 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100611 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200612 }
613 else if (!strcmp(args[0], "tune.maxrewrite")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.maxrewrite = atol(args[1]);
620 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
621 global.tune.maxrewrite = global.tune.bufsize / 2;
622 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100623 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
624 if (global.tune.client_rcvbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_rcvbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
637 if (global.tune.server_rcvbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_rcvbuf = atol(args[1]);
648 }
649 else if (!strcmp(args[0], "tune.sndbuf.client")) {
650 if (global.tune.client_sndbuf != 0) {
651 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT;
653 goto out;
654 }
655 if (*(args[1]) == 0) {
656 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT | ERR_FATAL;
658 goto out;
659 }
660 global.tune.client_sndbuf = atol(args[1]);
661 }
662 else if (!strcmp(args[0], "tune.sndbuf.server")) {
663 if (global.tune.server_sndbuf != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT;
666 goto out;
667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673 global.tune.server_sndbuf = atol(args[1]);
674 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200675 else if (!strcmp(args[0], "tune.pipesize")) {
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.tune.pipesize = atol(args[1]);
682 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100683 else if (!strcmp(args[0], "tune.http.cookielen")) {
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689 global.tune.cookie_len = atol(args[1]) + 1;
690 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200691 else if (!strcmp(args[0], "tune.http.maxhdr")) {
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 global.tune.max_http_hdr = atol(args[1]);
698 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100699 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
700#ifdef USE_ZLIB
701 if (*args[1]) {
702 global.tune.zlibmemlevel = atoi(args[1]);
703 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
704 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
705 file, linenum, args[0]);
706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
708 }
709 } else {
710 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715#else
716 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719#endif
720 }
721 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
722#ifdef USE_ZLIB
723 if (*args[1]) {
724 global.tune.zlibwindowsize = atoi(args[1]);
725 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
726 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
727 file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 } else {
732 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
733 file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737#else
738 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741#endif
742 }
William Lallemandf3747832012-11-09 12:33:10 +0100743 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
744 if (*args[1]) {
745 global.tune.comp_maxlevel = atoi(args[1]);
746 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
747 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
748 file, linenum, args[0]);
749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
751 }
752 } else {
753 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
754 file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 else if (!strcmp(args[0], "uid")) {
760 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200761 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200762 err_code |= ERR_ALERT;
763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770 global.uid = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "gid")) {
773 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200774 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT;
776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
783 global.gid = atol(args[1]);
784 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 /* user/group name handling */
786 else if (!strcmp(args[0], "user")) {
787 struct passwd *ha_user;
788 if (global.uid != 0) {
789 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200792 }
793 errno = 0;
794 ha_user = getpwnam(args[1]);
795 if (ha_user != NULL) {
796 global.uid = (int)ha_user->pw_uid;
797 }
798 else {
799 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200801 }
802 }
803 else if (!strcmp(args[0], "group")) {
804 struct group *ha_group;
805 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200806 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT;
808 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200809 }
810 errno = 0;
811 ha_group = getgrnam(args[1]);
812 if (ha_group != NULL) {
813 global.gid = (int)ha_group->gr_gid;
814 }
815 else {
816 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200818 }
819 }
820 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 global.nbproc = atol(args[1]);
828 }
829 else if (!strcmp(args[0], "maxconn")) {
830 if (global.maxconn != 0) {
831 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT;
833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840 global.maxconn = atol(args[1]);
841#ifdef SYSTEM_MAXCONN
842 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
843 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
844 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847#endif /* SYSTEM_MAXCONN */
848 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200849 else if (!strcmp(args[0], "maxsslconn")) {
850#ifdef USE_OPENSSL
851 if (*(args[1]) == 0) {
852 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
853 err_code |= ERR_ALERT | ERR_FATAL;
854 goto out;
855 }
856 global.maxsslconn = atol(args[1]);
857#else
Emeric Brun0914df82012-10-02 18:45:42 +0200858 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200861#endif
862 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200863 else if (!strcmp(args[0], "maxconnrate")) {
864 if (global.cps_lim != 0) {
865 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT;
867 goto out;
868 }
869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.cps_lim = atol(args[1]);
875 }
William Lallemandd85f9172012-11-09 17:05:39 +0100876 else if (!strcmp(args[0], "maxcomprate")) {
877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 global.comp_rate_lim = atoi(args[1]) * 1024;
883 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100884 else if (!strcmp(args[0], "maxpipes")) {
885 if (global.maxpipes != 0) {
886 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_ALERT;
888 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100889 }
890 if (*(args[1]) == 0) {
891 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100894 }
895 global.maxpipes = atol(args[1]);
896 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 else if (!strcmp(args[0], "maxzlibmem")) {
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
William Lallemande3a7d992012-11-20 11:25:20 +0100903 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100904 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100905 else if (!strcmp(args[0], "maxcompcpuusage")) {
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100912 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100913 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917}
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 else if (!strcmp(args[0], "ulimit-n")) {
920 if (global.rlimit_nofile != 0) {
921 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
925 if (*(args[1]) == 0) {
926 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930 global.rlimit_nofile = atol(args[1]);
931 }
932 else if (!strcmp(args[0], "chroot")) {
933 if (global.chroot != NULL) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 global.chroot = strdup(args[1]);
944 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200945 else if (!strcmp(args[0], "description")) {
946 int i, len=0;
947 char *d;
948
949 if (!*args[1]) {
950 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
951 file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 for(i=1; *args[i]; i++)
957 len += strlen(args[i])+1;
958
959 if (global.desc)
960 free(global.desc);
961
962 global.desc = d = (char *)calloc(1, len);
963
964 d += sprintf(d, "%s", args[1]);
965 for(i=2; *args[i]; i++)
966 d += sprintf(d, " %s", args[i]);
967 }
968 else if (!strcmp(args[0], "node")) {
969 int i;
970 char c;
971
972 for (i=0; args[1][i]; i++) {
973 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100974 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
975 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200976 break;
977 }
978
979 if (!i || args[1][i]) {
980 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
981 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
982 file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
986
987 if (global.node)
988 free(global.node);
989
990 global.node = strdup(args[1]);
991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "pidfile")) {
993 if (global.pidfile != NULL) {
994 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 }
1003 global.pidfile = strdup(args[1]);
1004 }
Emeric Bruned760922010-10-22 17:59:25 +02001005 else if (!strcmp(args[0], "unix-bind")) {
1006 int cur_arg = 1;
1007 while (*(args[cur_arg])) {
1008 if (!strcmp(args[cur_arg], "prefix")) {
1009 if (global.unix_bind.prefix != NULL) {
1010 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT;
1012 cur_arg += 2;
1013 continue;
1014 }
1015
1016 if (*(args[cur_arg+1]) == 0) {
1017 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020 }
1021 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "mode")) {
1027
1028 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "uid")) {
1034
1035 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "gid")) {
1041
1042 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1043 cur_arg += 2;
1044 continue;
1045 }
1046
1047 if (!strcmp(args[cur_arg], "user")) {
1048 struct passwd *user;
1049
1050 user = getpwnam(args[cur_arg + 1]);
1051 if (!user) {
1052 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1053 file, linenum, args[0], args[cur_arg + 1 ]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057
1058 global.unix_bind.ux.uid = user->pw_uid;
1059 cur_arg += 2;
1060 continue;
1061 }
1062
1063 if (!strcmp(args[cur_arg], "group")) {
1064 struct group *group;
1065
1066 group = getgrnam(args[cur_arg + 1]);
1067 if (!group) {
1068 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1069 file, linenum, args[0], args[cur_arg + 1 ]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073
1074 global.unix_bind.ux.gid = group->gr_gid;
1075 cur_arg += 2;
1076 continue;
1077 }
1078
Willy Tarreaub48f9582011-09-05 01:17:06 +02001079 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001080 file, linenum, args[0]);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084 }
William Lallemand0f99e342011-10-12 17:50:54 +02001085 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1086 /* delete previous herited or defined syslog servers */
1087 struct logsrv *back;
1088 struct logsrv *tmp;
1089
1090 if (*(args[1]) != 0) {
1091 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095
1096 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1097 LIST_DEL(&tmp->list);
1098 free(tmp);
1099 }
1100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001102 struct sockaddr_storage *sk;
1103 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001104 struct logsrv *logsrv;
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 if (*(args[1]) == 0 || *(args[2]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
William Lallemand0f99e342011-10-12 17:50:54 +02001111
1112 logsrv = calloc(1, sizeof(struct logsrv));
1113
1114 logsrv->facility = get_log_facility(args[2]);
1115 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120
William Lallemand0f99e342011-10-12 17:50:54 +02001121 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001123 logsrv->level = get_log_level(args[3]);
1124 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001127 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 }
1130
William Lallemand0f99e342011-10-12 17:50:54 +02001131 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001132 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001133 logsrv->minlvl = get_log_level(args[4]);
1134 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001135 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001137 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001138 }
1139 }
1140
Willy Tarreau902636f2013-03-10 19:44:48 +01001141 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001142 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001143 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001144 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001145 free(logsrv);
1146 goto out;
1147 }
1148 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001149
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001150 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001151 if (port1 != port2) {
1152 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1153 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001154 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001155 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001156 goto out;
1157 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001158
William Lallemand0f99e342011-10-12 17:50:54 +02001159 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001160 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001161 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163
William Lallemand0f99e342011-10-12 17:50:54 +02001164 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001165 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001166 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1167 char *name;
1168 int len;
1169
1170 if (global.log_send_hostname != NULL) {
1171 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT;
1173 goto out;
1174 }
1175
1176 if (*(args[1]))
1177 name = args[1];
1178 else
1179 name = hostname;
1180
1181 len = strlen(name);
1182
1183 /* We'll add a space after the name to respect the log format */
1184 free(global.log_send_hostname);
1185 global.log_send_hostname = malloc(len + 2);
1186 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1187 }
Kevinm48936af2010-12-22 16:08:21 +00001188 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
1193 }
1194 free(global.log_tag);
1195 global.log_tag = strdup(args[1]);
1196 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001197 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1198 if (global.spread_checks != 0) {
1199 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001207 }
1208 global.spread_checks = atol(args[1]);
1209 if (global.spread_checks < 0 || global.spread_checks > 50) {
1210 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001211 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001214 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1215#ifdef USE_CPU_AFFINITY
1216 int cur_arg, i;
1217 unsigned int proc = 0;
1218 unsigned long cpus = 0;
1219
1220 if (strcmp(args[1], "all") == 0)
1221 proc = 0xFFFFFFFF;
1222 else if (strcmp(args[1], "odd") == 0)
1223 proc = 0x55555555;
1224 else if (strcmp(args[1], "even") == 0)
1225 proc = 0xAAAAAAAA;
1226 else {
1227 proc = atoi(args[1]);
1228 if (proc >= 1 && proc <= 32)
1229 proc = 1 << (proc - 1);
1230 }
1231
1232 if (!proc || !*args[2]) {
1233 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1234 file, linenum, args[0]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 cur_arg = 2;
1240 while (*args[cur_arg]) {
1241 unsigned int low, high;
1242
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001243 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001244 char *dash = strchr(args[cur_arg], '-');
1245
1246 low = high = str2uic(args[cur_arg]);
1247 if (dash)
1248 high = str2uic(dash + 1);
1249
1250 if (high < low) {
1251 unsigned int swap = low;
1252 low = high;
1253 high = swap;
1254 }
1255
1256 if (low < 0 || high >= sizeof(long) * 8) {
1257 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1258 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 while (low <= high)
1264 cpus |= 1UL << low++;
1265 }
1266 else {
1267 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1268 file, linenum, args[0], args[cur_arg]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 cur_arg++;
1273 }
1274 for (i = 0; i < 32; i++)
1275 if (proc & (1 << i))
1276 global.cpu_map[i] = cpus;
1277#else
1278 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281#endif
1282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001284 struct cfg_kw_list *kwl;
1285 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001286 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001287
1288 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1289 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1290 if (kwl->kw[index].section != CFG_GLOBAL)
1291 continue;
1292 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001293 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001294 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001295 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001297 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001298 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001299 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_WARN;
1301 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001302 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001304 }
1305 }
1306 }
1307
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001311
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001313 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315}
1316
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001317void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001319 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 defproxy.mode = PR_MODE_TCP;
1321 defproxy.state = PR_STNEW;
1322 defproxy.maxconn = cfg_maxpconn;
1323 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001324
Simon Horman66183002013-02-23 10:16:43 +09001325 defproxy.defsrv.check.inter = DEF_CHKINTR;
1326 defproxy.defsrv.check.fastinter = 0;
1327 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001328 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1329 defproxy.defsrv.agent.fastinter = 0;
1330 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001331 defproxy.defsrv.check.rise = DEF_RISETIME;
1332 defproxy.defsrv.check.fall = DEF_FALLTIME;
1333 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1334 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001335 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001336 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001337 defproxy.defsrv.maxqueue = 0;
1338 defproxy.defsrv.minconn = 0;
1339 defproxy.defsrv.maxconn = 0;
1340 defproxy.defsrv.slowstart = 0;
1341 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1342 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1343 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344}
1345
Willy Tarreauade5ec42010-01-28 19:33:49 +01001346
1347static int create_cond_regex_rule(const char *file, int line,
1348 struct proxy *px, int dir, int action, int flags,
1349 const char *cmd, const char *reg, const char *repl,
1350 const char **cond_start)
1351{
1352 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001353 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001354 const char *err;
1355 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001356 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001357
1358 if (px == &defproxy) {
1359 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (*reg == 0) {
1365 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto err;
1368 }
1369
1370 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1371 err_code |= ERR_WARN;
1372
Willy Tarreau5321c422010-01-28 20:35:13 +01001373 if (cond_start &&
1374 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001375 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1376 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1377 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001378 err_code |= ERR_ALERT | ERR_FATAL;
1379 goto err;
1380 }
1381 }
1382 else if (cond_start && **cond_start) {
1383 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1384 file, line, cmd, *cond_start);
1385 err_code |= ERR_ALERT | ERR_FATAL;
1386 goto err;
1387 }
1388
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001389 err_code |= warnif_cond_conflicts(cond,
1390 (dir == SMP_OPT_DIR_REQ) ?
1391 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1392 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1393 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001394
Willy Tarreauade5ec42010-01-28 19:33:49 +01001395 preg = calloc(1, sizeof(regex_t));
1396 if (!preg) {
1397 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1398 err_code = ERR_ALERT | ERR_FATAL;
1399 goto err;
1400 }
1401
1402 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1403 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1404 err_code = ERR_ALERT | ERR_FATAL;
1405 goto err;
1406 }
1407
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001408 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001409 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001410 if (repl && err) {
1411 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1412 file, line, cmd, *err);
1413 err_code |= ERR_ALERT | ERR_FATAL;
1414 goto err;
1415 }
1416
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001417 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001418 err_code |= ERR_WARN;
1419
Willy Tarreauf4068b62012-05-08 17:37:49 +02001420 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001421 return err_code;
1422 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001423 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001424 free(preg);
1425 return err_code;
1426}
1427
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001429 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001430 * Returns the error code, 0 if OK, or any combination of :
1431 * - ERR_ABORT: must abort ASAP
1432 * - ERR_FATAL: we can continue parsing but not start the service
1433 * - ERR_WARN: a warning has been emitted
1434 * - ERR_ALERT: an alert has been emitted
1435 * Only the two first ones can stop processing, the two others are just
1436 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001438int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1439{
1440 static struct peers *curpeers = NULL;
1441 struct peer *newpeer = NULL;
1442 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001443 struct bind_conf *bind_conf;
1444 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001445 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001446 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001447
1448 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001449 if (!*args[1]) {
1450 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1451 err_code |= ERR_ALERT | ERR_FATAL;
1452 goto out;
1453 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001454
1455 err = invalid_char(args[1]);
1456 if (err) {
1457 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1458 file, linenum, *err, args[0], args[1]);
1459 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001460 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001461 }
1462
1463 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1464 /*
1465 * If there are two proxies with the same name only following
1466 * combinations are allowed:
1467 */
1468 if (strcmp(curpeers->id, args[1]) == 0) {
1469 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1470 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1471 err_code |= ERR_WARN;
1472 }
1473 }
1474
1475 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1476 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1477 err_code |= ERR_ALERT | ERR_ABORT;
1478 goto out;
1479 }
1480
1481 curpeers->next = peers;
1482 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001483 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001484 curpeers->conf.line = linenum;
1485 curpeers->last_change = now.tv_sec;
1486 curpeers->id = strdup(args[1]);
1487 }
1488 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001489 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001490 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001491 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001492
1493 if (!*args[2]) {
1494 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1495 file, linenum, args[0]);
1496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto out;
1498 }
1499
1500 err = invalid_char(args[1]);
1501 if (err) {
1502 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1503 file, linenum, *err, args[1]);
1504 err_code |= ERR_ALERT | ERR_FATAL;
1505 goto out;
1506 }
1507
1508 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1509 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1510 err_code |= ERR_ALERT | ERR_ABORT;
1511 goto out;
1512 }
1513
1514 /* the peers are linked backwards first */
1515 curpeers->count++;
1516 newpeer->next = curpeers->remote;
1517 curpeers->remote = newpeer;
1518 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001519 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001520 newpeer->conf.line = linenum;
1521
1522 newpeer->last_change = now.tv_sec;
1523 newpeer->id = strdup(args[1]);
1524
Willy Tarreau902636f2013-03-10 19:44:48 +01001525 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001526 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001527 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001530 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001531
1532 proto = protocol_by_family(sk->ss_family);
1533 if (!proto || !proto->connect) {
1534 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1535 file, linenum, args[0], args[1]);
1536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001539
1540 if (port1 != port2) {
1541 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1542 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
1545 }
1546
Willy Tarreau2aa38802013-02-20 19:20:59 +01001547 if (!port1) {
1548 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1549 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001550 err_code |= ERR_ALERT | ERR_FATAL;
1551 goto out;
1552 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001553
Emeric Brun32da3c42010-09-23 18:39:19 +02001554 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001555 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001556 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001557 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001558
Emeric Brun32da3c42010-09-23 18:39:19 +02001559 if (strcmp(newpeer->id, localpeer) == 0) {
1560 /* Current is local peer, it define a frontend */
1561 newpeer->local = 1;
1562
1563 if (!curpeers->peers_fe) {
1564 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1565 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1566 err_code |= ERR_ALERT | ERR_ABORT;
1567 goto out;
1568 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001569
Willy Tarreau237250c2011-07-29 01:49:03 +02001570 init_new_proxy(curpeers->peers_fe);
1571 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001572
1573 curpeers->peers_fe->last_change = now.tv_sec;
1574 curpeers->peers_fe->id = strdup(args[1]);
1575 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001576 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001577 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1578 curpeers->peers_fe->timeout.connect = 5000;
1579 curpeers->peers_fe->accept = peer_accept;
1580 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001581 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1582 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001583
1584 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1585
Willy Tarreau902636f2013-03-10 19:44:48 +01001586 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1587 if (errmsg && *errmsg) {
1588 indent_msg(&errmsg, 2);
1589 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001590 }
1591 else
1592 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1593 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001594 err_code |= ERR_FATAL;
1595 goto out;
1596 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001597
1598 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1599 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1600 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1601 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1602 l->accept = session_accept;
1603 l->handler = process_session;
1604 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1605 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1606 global.maxsock += l->maxconn;
1607 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001608 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001609 else {
1610 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1611 file, linenum, args[0], args[1],
1612 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1613 err_code |= ERR_FATAL;
1614 goto out;
1615 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001616 }
1617 } /* neither "peer" nor "peers" */
1618 else if (*args[0] != 0) {
1619 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
1622 }
1623
1624out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001625 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001626 return err_code;
1627}
1628
Simon Horman69d29f92013-02-23 15:14:19 +09001629static int init_check(struct check *check, int type, const char * file, int linenum)
1630{
1631 check->type = type;
1632
1633 /* Allocate buffer for requests... */
1634 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1635 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1636 return ERR_ALERT | ERR_ABORT;
1637 }
1638 check->bi->size = global.tune.chksize;
1639
1640 /* Allocate buffer for responses... */
1641 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1642 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1643 return ERR_ALERT | ERR_ABORT;
1644 }
1645 check->bo->size = global.tune.chksize;
1646
1647 /* Allocate buffer for partial results... */
1648 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1649 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1650 return ERR_ALERT | ERR_ABORT;
1651 }
1652
1653 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1654
1655 return 0;
1656}
Emeric Brun32da3c42010-09-23 18:39:19 +02001657
Willy Tarreau3842f002009-06-14 11:39:52 +02001658int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659{
1660 static struct proxy *curproxy = NULL;
1661 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001662 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001663 int rc;
1664 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001665 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001666 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001667 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001668 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001669 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670
Willy Tarreau977b8e42006-12-29 14:19:17 +01001671 if (!strcmp(args[0], "listen"))
1672 rc = PR_CAP_LISTEN;
1673 else if (!strcmp(args[0], "frontend"))
1674 rc = PR_CAP_FE | PR_CAP_RS;
1675 else if (!strcmp(args[0], "backend"))
1676 rc = PR_CAP_BE | PR_CAP_RS;
1677 else if (!strcmp(args[0], "ruleset"))
1678 rc = PR_CAP_RS;
1679 else
1680 rc = PR_CAP_NONE;
1681
1682 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 if (!*args[1]) {
1684 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1685 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1686 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001687 err_code |= ERR_ALERT | ERR_ABORT;
1688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001689 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001690
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001691 err = invalid_char(args[1]);
1692 if (err) {
1693 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1694 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001696 }
1697
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001698 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1699 /*
1700 * If there are two proxies with the same name only following
1701 * combinations are allowed:
1702 *
1703 * listen backend frontend ruleset
1704 * listen - - - -
1705 * backend - - OK -
1706 * frontend - OK - -
1707 * ruleset - - - -
1708 */
1709
1710 if (!strcmp(curproxy->id, args[1]) &&
1711 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1712 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001713 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1714 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1715 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001717 }
1718 }
1719
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1721 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001722 err_code |= ERR_ALERT | ERR_ABORT;
1723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001725
Willy Tarreau97cb7802010-01-03 20:23:58 +01001726 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 curproxy->next = proxy;
1728 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001729 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1730 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001731 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001733 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734
1735 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001736 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001737 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001738
Willy Tarreau4348fad2012-09-20 16:48:07 +02001739 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1740
Willy Tarreau902636f2013-03-10 19:44:48 +01001741 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1742 if (errmsg && *errmsg) {
1743 indent_msg(&errmsg, 2);
1744 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001745 }
1746 else
1747 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1748 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001749 err_code |= ERR_FATAL;
1750 goto out;
1751 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001752
Willy Tarreau4348fad2012-09-20 16:48:07 +02001753 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001754 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756 }
1757
1758 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001759 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001760 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001761
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001764 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001765 curproxy->no_options = defproxy.no_options;
1766 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001767 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001768 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001769 curproxy->except_net = defproxy.except_net;
1770 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001771 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001772 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001774 if (defproxy.fwdfor_hdr_len) {
1775 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1776 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1777 }
1778
Willy Tarreaub86db342009-11-30 11:50:16 +01001779 if (defproxy.orgto_hdr_len) {
1780 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1781 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1782 }
1783
Mark Lamourinec2247f02012-01-04 13:02:01 -05001784 if (defproxy.server_id_hdr_len) {
1785 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1786 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1787 }
1788
Willy Tarreau977b8e42006-12-29 14:19:17 +01001789 if (curproxy->cap & PR_CAP_FE) {
1790 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001791 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001792 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793
1794 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001795 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1796 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001797
1798 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800
Willy Tarreau977b8e42006-12-29 14:19:17 +01001801 if (curproxy->cap & PR_CAP_BE) {
1802 curproxy->fullconn = defproxy.fullconn;
1803 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001805 if (defproxy.check_req) {
1806 curproxy->check_req = calloc(1, defproxy.check_len);
1807 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1808 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001809 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001811 if (defproxy.expect_str) {
1812 curproxy->expect_str = strdup(defproxy.expect_str);
1813 if (defproxy.expect_regex) {
1814 /* note: this regex is known to be valid */
1815 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1816 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1817 }
1818 }
1819
Willy Tarreau67402132012-05-31 20:40:20 +02001820 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001821 if (defproxy.cookie_name)
1822 curproxy->cookie_name = strdup(defproxy.cookie_name);
1823 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001824 if (defproxy.cookie_domain)
1825 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001826
Willy Tarreau31936852010-10-06 16:59:56 +02001827 if (defproxy.cookie_maxidle)
1828 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1829
1830 if (defproxy.cookie_maxlife)
1831 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1832
Emeric Brun647caf12009-06-30 17:57:00 +02001833 if (defproxy.rdp_cookie_name)
1834 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1835 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1836
Willy Tarreau01732802007-11-01 22:48:15 +01001837 if (defproxy.url_param_name)
1838 curproxy->url_param_name = strdup(defproxy.url_param_name);
1839 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001840
Benoitaffb4812009-03-25 13:02:10 +01001841 if (defproxy.hh_name)
1842 curproxy->hh_name = strdup(defproxy.hh_name);
1843 curproxy->hh_len = defproxy.hh_len;
1844 curproxy->hh_match_domain = defproxy.hh_match_domain;
1845
Willy Tarreauef9a3602012-12-08 22:29:20 +01001846 if (defproxy.conn_src.iface_name)
1847 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1848 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001849 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001850#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001851 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001852#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001855 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001856 if (defproxy.capture_name)
1857 curproxy->capture_name = strdup(defproxy.capture_name);
1858 curproxy->capture_namelen = defproxy.capture_namelen;
1859 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861
Willy Tarreau977b8e42006-12-29 14:19:17 +01001862 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001863 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001864 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001865 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001866 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001867 curproxy->uri_auth = defproxy.uri_auth;
1868 curproxy->mon_net = defproxy.mon_net;
1869 curproxy->mon_mask = defproxy.mon_mask;
1870 if (defproxy.monitor_uri)
1871 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1872 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001873 if (defproxy.defbe.name)
1874 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001875
1876 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001877 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1878 if (curproxy->conf.logformat_string &&
1879 curproxy->conf.logformat_string != default_http_log_format &&
1880 curproxy->conf.logformat_string != default_tcp_log_format &&
1881 curproxy->conf.logformat_string != clf_http_log_format)
1882 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1883
1884 if (defproxy.conf.lfs_file) {
1885 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1886 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1887 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001888 }
1889
1890 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001891 curproxy->timeout.connect = defproxy.timeout.connect;
1892 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001893 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001894 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001895 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001896 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001897 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001898 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001899 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001900 }
1901
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001903
1904 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001905 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001906 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001907 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001908 LIST_INIT(&node->list);
1909 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1910 }
1911
Willy Tarreau62a61232013-04-12 18:13:46 +02001912 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1913 if (curproxy->conf.uniqueid_format_string)
1914 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1915
1916 if (defproxy.conf.uif_file) {
1917 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1918 curproxy->conf.uif_line = defproxy.conf.uif_line;
1919 }
William Lallemanda73203e2012-03-12 12:48:57 +01001920
1921 /* copy default header unique id */
1922 if (defproxy.header_unique_id)
1923 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1924
William Lallemand82fe75c2012-10-23 10:25:10 +02001925 /* default compression options */
1926 if (defproxy.comp != NULL) {
1927 curproxy->comp = calloc(1, sizeof(struct comp));
1928 curproxy->comp->algos = defproxy.comp->algos;
1929 curproxy->comp->types = defproxy.comp->types;
1930 }
1931
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001933 curproxy->conf.used_listener_id = EB_ROOT;
1934 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001935
Willy Tarreau93893792009-07-23 13:19:11 +02001936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 }
1938 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1939 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001940 /* FIXME-20070101: we should do this too at the end of the
1941 * config parsing to free all default values.
1942 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001943 free(defproxy.check_req);
1944 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001945 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001946 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001947 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001948 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001949 free(defproxy.capture_name);
1950 free(defproxy.monitor_uri);
1951 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001952 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001953 free(defproxy.fwdfor_hdr_name);
1954 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001955 free(defproxy.orgto_hdr_name);
1956 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001957 free(defproxy.server_id_hdr_name);
1958 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001959 free(defproxy.expect_str);
1960 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001961
Willy Tarreau62a61232013-04-12 18:13:46 +02001962 if (defproxy.conf.logformat_string != default_http_log_format &&
1963 defproxy.conf.logformat_string != default_tcp_log_format &&
1964 defproxy.conf.logformat_string != clf_http_log_format)
1965 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001966
Willy Tarreau62a61232013-04-12 18:13:46 +02001967 free(defproxy.conf.uniqueid_format_string);
1968 free(defproxy.conf.lfs_file);
1969 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001970
Willy Tarreaua534fea2008-08-03 12:19:50 +02001971 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001972 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001973
Willy Tarreaubaaee002006-06-26 02:48:02 +02001974 /* we cannot free uri_auth because it might already be used */
1975 init_default_instance();
1976 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001977 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1978 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001979 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 }
1982 else if (curproxy == NULL) {
1983 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001987
1988 /* update the current file and line being parsed */
1989 curproxy->conf.args.file = curproxy->conf.file;
1990 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001991
1992 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001994 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001995 int cur_arg;
1996
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 if (curproxy == &defproxy) {
1998 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004
Willy Tarreau24709282013-03-10 21:32:12 +01002005 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002006 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002008 err_code |= ERR_ALERT | ERR_FATAL;
2009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002010 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002011
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002012 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002013
2014 /* use default settings for unix sockets */
2015 bind_conf->ux.uid = global.unix_bind.ux.uid;
2016 bind_conf->ux.gid = global.unix_bind.ux.gid;
2017 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002018
2019 /* NOTE: the following line might create several listeners if there
2020 * are comma-separated IPs or port ranges. So all further processing
2021 * will have to be applied to all listeners created after last_listen.
2022 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002023 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2024 if (errmsg && *errmsg) {
2025 indent_msg(&errmsg, 2);
2026 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002027 }
2028 else
2029 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2030 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
2033 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002034
Willy Tarreau4348fad2012-09-20 16:48:07 +02002035 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2036 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002037 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002038 }
2039
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002040 cur_arg = 2;
2041 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002042 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002043 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002044 char *err;
2045
Willy Tarreau26982662012-09-12 23:17:10 +02002046 kw = bind_find_kw(args[cur_arg]);
2047 if (kw) {
2048 char *err = NULL;
2049 int code;
2050
2051 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002052 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2053 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002054 cur_arg += 1 + kw->skip ;
2055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
2057 }
2058
Willy Tarreau4348fad2012-09-20 16:48:07 +02002059 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002060 err_code |= code;
2061
2062 if (code) {
2063 if (err && *err) {
2064 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002065 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002066 }
2067 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002068 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2069 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002070 if (code & ERR_FATAL) {
2071 free(err);
2072 cur_arg += 1 + kw->skip;
2073 goto out;
2074 }
2075 }
2076 free(err);
2077 cur_arg += 1 + kw->skip;
2078 continue;
2079 }
2080
Willy Tarreau8638f482012-09-18 18:01:17 +02002081 err = NULL;
2082 if (!bind_dumped) {
2083 bind_dump_kws(&err);
2084 indent_msg(&err, 4);
2085 bind_dumped = 1;
2086 }
2087
2088 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2089 file, linenum, args[0], args[1], args[cur_arg],
2090 err ? " Registered keywords :" : "", err ? err : "");
2091 free(err);
2092
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002095 }
Willy Tarreau93893792009-07-23 13:19:11 +02002096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 }
2098 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2099 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2100 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002106 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002107
Willy Tarreaubaaee002006-06-26 02:48:02 +02002108 /* flush useless bits */
2109 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002112 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002113 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115
Willy Tarreau1c47f852006-07-09 08:22:27 +02002116 if (!*args[1]) {
2117 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2118 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002119 err_code |= ERR_ALERT | ERR_FATAL;
2120 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002121 }
2122
Willy Tarreaua534fea2008-08-03 12:19:50 +02002123 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002124 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002125 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002126 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002127 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2128
Willy Tarreau93893792009-07-23 13:19:11 +02002129 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2132 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2133 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2134 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2135 else {
2136 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_ALERT | ERR_FATAL;
2138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139 }
2140 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002141 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002142 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002143
2144 if (curproxy == &defproxy) {
2145 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2146 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002147 err_code |= ERR_ALERT | ERR_FATAL;
2148 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002149 }
2150
2151 if (!*args[1]) {
2152 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002156 }
2157
2158 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002159 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002160
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002161 if (curproxy->uuid <= 0) {
2162 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002163 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002166 }
2167
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002168 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2169 if (node) {
2170 struct proxy *target = container_of(node, struct proxy, conf.id);
2171 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2172 file, linenum, proxy_type_str(curproxy), curproxy->id,
2173 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
2176 }
2177 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002178 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002179 else if (!strcmp(args[0], "description")) {
2180 int i, len=0;
2181 char *d;
2182
Cyril Bonté99ed3272010-01-24 23:29:44 +01002183 if (curproxy == &defproxy) {
2184 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2185 file, linenum, args[0]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002190 if (!*args[1]) {
2191 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2192 file, linenum, args[0]);
2193 return -1;
2194 }
2195
2196 for(i=1; *args[i]; i++)
2197 len += strlen(args[i])+1;
2198
2199 d = (char *)calloc(1, len);
2200 curproxy->desc = d;
2201
2202 d += sprintf(d, "%s", args[1]);
2203 for(i=2; *args[i]; i++)
2204 d += sprintf(d, " %s", args[i]);
2205
2206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2208 curproxy->state = PR_STSTOPPED;
2209 }
2210 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2211 curproxy->state = PR_STNEW;
2212 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002213 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2214 int cur_arg = 1;
2215 unsigned int set = 0;
2216
2217 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002218 unsigned int low, high;
2219
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002220 if (strcmp(args[cur_arg], "all") == 0) {
2221 set = 0;
2222 break;
2223 }
2224 else if (strcmp(args[cur_arg], "odd") == 0) {
2225 set |= 0x55555555;
2226 }
2227 else if (strcmp(args[cur_arg], "even") == 0) {
2228 set |= 0xAAAAAAAA;
2229 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002230 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002231 char *dash = strchr(args[cur_arg], '-');
2232
2233 low = high = str2uic(args[cur_arg]);
2234 if (dash)
2235 high = str2uic(dash + 1);
2236
2237 if (high < low) {
2238 unsigned int swap = low;
2239 low = high;
2240 high = swap;
2241 }
2242
2243 if (low < 1 || high > 32) {
2244 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002248 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002249
2250 if (high > global.nbproc) {
2251 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2252 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002254 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002255 while (low <= high)
2256 set |= 1 << (low++ - 1);
2257 }
2258 else {
2259 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2260 file, linenum, args[0]);
2261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002263 }
2264 cur_arg++;
2265 }
2266 curproxy->bind_proc = set;
2267 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002268 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002269 if (curproxy == &defproxy) {
2270 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002273 }
2274
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002275 err = invalid_char(args[1]);
2276 if (err) {
2277 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2278 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002280 }
2281
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002282 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002283 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2284 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002287 }
2288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002289 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2290 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291
Willy Tarreau977b8e42006-12-29 14:19:17 +01002292 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002294
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 if (*(args[1]) == 0) {
2296 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002301
Willy Tarreau67402132012-05-31 20:40:20 +02002302 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002303 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002304 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002305 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 curproxy->cookie_name = strdup(args[1]);
2307 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002308
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 cur_arg = 2;
2310 while (*(args[cur_arg])) {
2311 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002312 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 }
2314 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002315 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 }
2317 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002318 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 }
2320 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002321 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 }
2323 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002324 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002325 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002326 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002327 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002330 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002332 else if (!strcmp(args[cur_arg], "httponly")) {
2333 curproxy->ck_opts |= PR_CK_HTTPONLY;
2334 }
2335 else if (!strcmp(args[cur_arg], "secure")) {
2336 curproxy->ck_opts |= PR_CK_SECURE;
2337 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002338 else if (!strcmp(args[cur_arg], "domain")) {
2339 if (!*args[cur_arg + 1]) {
2340 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2341 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002344 }
2345
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002346 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002347 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002348 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2349 " dots nor does not start with a dot."
2350 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002351 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002352 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002353 }
2354
2355 err = invalid_domainchar(args[cur_arg + 1]);
2356 if (err) {
2357 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2358 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002361 }
2362
Willy Tarreau68a897b2009-12-03 23:28:34 +01002363 if (!curproxy->cookie_domain) {
2364 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2365 } else {
2366 /* one domain was already specified, add another one by
2367 * building the string which will be returned along with
2368 * the cookie.
2369 */
2370 char *new_ptr;
2371 int new_len = strlen(curproxy->cookie_domain) +
2372 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2373 new_ptr = malloc(new_len);
2374 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2375 free(curproxy->cookie_domain);
2376 curproxy->cookie_domain = new_ptr;
2377 }
Willy Tarreau31936852010-10-06 16:59:56 +02002378 cur_arg++;
2379 }
2380 else if (!strcmp(args[cur_arg], "maxidle")) {
2381 unsigned int maxidle;
2382 const char *res;
2383
2384 if (!*args[cur_arg + 1]) {
2385 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2386 file, linenum, args[cur_arg]);
2387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
2389 }
2390
2391 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2392 if (res) {
2393 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2394 file, linenum, *res, args[cur_arg]);
2395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
2397 }
2398 curproxy->cookie_maxidle = maxidle;
2399 cur_arg++;
2400 }
2401 else if (!strcmp(args[cur_arg], "maxlife")) {
2402 unsigned int maxlife;
2403 const char *res;
2404
2405 if (!*args[cur_arg + 1]) {
2406 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2407 file, linenum, args[cur_arg]);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
2410 }
2411
2412 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2413 if (res) {
2414 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2415 file, linenum, *res, args[cur_arg]);
2416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
2418 }
2419 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002420 cur_arg++;
2421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002423 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 }
2428 cur_arg++;
2429 }
Willy Tarreau67402132012-05-31 20:40:20 +02002430 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2432 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
2435
Willy Tarreau67402132012-05-31 20:40:20 +02002436 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2438 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002441
Willy Tarreau67402132012-05-31 20:40:20 +02002442 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002443 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2444 file, linenum);
2445 err_code |= ERR_ALERT | ERR_FATAL;
2446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002448 else if (!strcmp(args[0], "persist")) { /* persist */
2449 if (*(args[1]) == 0) {
2450 Alert("parsing [%s:%d] : missing persist method.\n",
2451 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002454 }
2455
2456 if (!strncmp(args[1], "rdp-cookie", 10)) {
2457 curproxy->options2 |= PR_O2_RDPC_PRST;
2458
Emeric Brunb982a3d2010-01-04 15:45:53 +01002459 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002460 const char *beg, *end;
2461
2462 beg = args[1] + 11;
2463 end = strchr(beg, ')');
2464
2465 if (!end || end == beg) {
2466 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2467 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002470 }
2471
2472 free(curproxy->rdp_cookie_name);
2473 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2474 curproxy->rdp_cookie_len = end-beg;
2475 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002476 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002477 free(curproxy->rdp_cookie_name);
2478 curproxy->rdp_cookie_name = strdup("msts");
2479 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2480 }
2481 else { /* syntax */
2482 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2483 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002486 }
2487 }
2488 else {
2489 Alert("parsing [%s:%d] : unknown persist method.\n",
2490 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002493 }
2494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002496 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002498 if (curproxy == &defproxy) {
2499 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
2502 }
2503
Willy Tarreau977b8e42006-12-29 14:19:17 +01002504 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002506
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002508 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002509 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }
2513 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002514 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 curproxy->appsession_name = strdup(args[1]);
2516 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2517 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002518 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2519 if (err) {
2520 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2521 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002524 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002525 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002526
Willy Tarreau51041c72007-09-09 21:56:53 +02002527 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2528 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_ABORT;
2530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002532
2533 cur_arg = 6;
2534 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002535 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2536 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002537 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002538 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002539 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002540 } else if (!strcmp(args[cur_arg], "prefix")) {
2541 curproxy->options2 |= PR_O2_AS_PFX;
2542 } else if (!strcmp(args[cur_arg], "mode")) {
2543 if (!*args[cur_arg + 1]) {
2544 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2545 file, linenum, args[0], args[cur_arg]);
2546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
2548 }
2549
2550 cur_arg++;
2551 if (!strcmp(args[cur_arg], "query-string")) {
2552 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2553 curproxy->options2 |= PR_O2_AS_M_QS;
2554 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2555 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2556 curproxy->options2 |= PR_O2_AS_M_PP;
2557 } else {
2558 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
2561 }
2562 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002563 cur_arg++;
2564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 } /* Url App Session */
2566 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002567 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002571 if (curproxy == &defproxy) {
2572 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
2575 }
2576
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 if (*(args[4]) == 0) {
2578 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2579 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002583 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 curproxy->capture_name = strdup(args[2]);
2585 curproxy->capture_namelen = strlen(curproxy->capture_name);
2586 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 curproxy->to_log |= LW_COOKIE;
2588 }
2589 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2590 struct cap_hdr *hdr;
2591
2592 if (curproxy == &defproxy) {
2593 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
2597
2598 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2599 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2600 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002601 err_code |= ERR_ALERT | ERR_FATAL;
2602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 }
2604
2605 hdr = calloc(sizeof(struct cap_hdr), 1);
2606 hdr->next = curproxy->req_cap;
2607 hdr->name = strdup(args[3]);
2608 hdr->namelen = strlen(args[3]);
2609 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002610 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 hdr->index = curproxy->nb_req_cap++;
2612 curproxy->req_cap = hdr;
2613 curproxy->to_log |= LW_REQHDR;
2614 }
2615 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2616 struct cap_hdr *hdr;
2617
2618 if (curproxy == &defproxy) {
2619 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
2623
2624 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2625 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2626 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 }
2630 hdr = calloc(sizeof(struct cap_hdr), 1);
2631 hdr->next = curproxy->rsp_cap;
2632 hdr->name = strdup(args[3]);
2633 hdr->namelen = strlen(args[3]);
2634 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002635 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 hdr->index = curproxy->nb_rsp_cap++;
2637 curproxy->rsp_cap = hdr;
2638 curproxy->to_log |= LW_RSPHDR;
2639 }
2640 else {
2641 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2642 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 }
2646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002648 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002649 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002650
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 if (*(args[1]) == 0) {
2652 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 }
2657 curproxy->conn_retries = atol(args[1]);
2658 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002659 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002660 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002661
2662 if (curproxy == &defproxy) {
2663 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
Willy Tarreau20b0de52012-12-24 15:45:22 +01002668 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2669 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2670 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2671 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002672 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002673 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2674 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002675 file, linenum, args[0]);
2676 err_code |= ERR_WARN;
2677 }
2678
Willy Tarreauff011f22011-01-06 17:51:27 +01002679 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002680
Willy Tarreauff011f22011-01-06 17:51:27 +01002681 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002682 err_code |= ERR_ALERT | ERR_ABORT;
2683 goto out;
2684 }
2685
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002686 err_code |= warnif_cond_conflicts(rule->cond,
2687 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2688 file, linenum);
2689
Willy Tarreauff011f22011-01-06 17:51:27 +01002690 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002691 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002692 else if (!strcmp(args[0], "http-response")) { /* response access control */
2693 struct http_res_rule *rule;
2694
2695 if (curproxy == &defproxy) {
2696 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700
2701 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2702 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2703 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2704 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2705 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2706 file, linenum, args[0]);
2707 err_code |= ERR_WARN;
2708 }
2709
2710 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2711
2712 if (!rule) {
2713 err_code |= ERR_ALERT | ERR_ABORT;
2714 goto out;
2715 }
2716
2717 err_code |= warnif_cond_conflicts(rule->cond,
2718 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2719 file, linenum);
2720
2721 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2722 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002723 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2724 /* set the header name and length into the proxy structure */
2725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2726 err_code |= ERR_WARN;
2727
2728 if (!*args[1]) {
2729 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2730 file, linenum, args[0]);
2731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
2733 }
2734
2735 /* set the desired header name */
2736 free(curproxy->server_id_hdr_name);
2737 curproxy->server_id_hdr_name = strdup(args[1]);
2738 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2739 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002740 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002741 if (curproxy == &defproxy) {
2742 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002745 }
2746
Willy Tarreauef6494c2010-01-28 17:12:36 +01002747 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002748 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2749 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002752 }
2753
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002754 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2755 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2756 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002759 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002760
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002761 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002762 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002763 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002764 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002765 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002766
Cyril Bonté99ed3272010-01-24 23:29:44 +01002767 if (curproxy == &defproxy) {
2768 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
2772
Willy Tarreau4baae242012-12-27 12:00:31 +01002773 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2774 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2775 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002778 }
2779
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002780 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002781 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002782 err_code |= warnif_cond_conflicts(rule->cond,
2783 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2784 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002785 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002786 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002787 struct switching_rule *rule;
2788
Willy Tarreaub099aca2008-10-12 17:26:37 +02002789 if (curproxy == &defproxy) {
2790 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002793 }
2794
Willy Tarreau55ea7572007-06-17 19:56:27 +02002795 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002796 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002797
2798 if (*(args[1]) == 0) {
2799 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002802 }
2803
Willy Tarreauef6494c2010-01-28 17:12:36 +01002804 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002805 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2806 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002807 err_code |= ERR_ALERT | ERR_FATAL;
2808 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002809 }
2810
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002811 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2812 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2813 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002816 }
2817
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002818 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002819
Willy Tarreau55ea7572007-06-17 19:56:27 +02002820 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2821 rule->cond = cond;
2822 rule->be.name = strdup(args[1]);
2823 LIST_INIT(&rule->list);
2824 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2825 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002826 else if (strcmp(args[0], "use-server") == 0) {
2827 struct server_rule *rule;
2828
2829 if (curproxy == &defproxy) {
2830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834
2835 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2836 err_code |= ERR_WARN;
2837
2838 if (*(args[1]) == 0) {
2839 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
2843
2844 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2845 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2846 file, linenum, args[0]);
2847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
2849 }
2850
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002851 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2852 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2853 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002854 err_code |= ERR_ALERT | ERR_FATAL;
2855 goto out;
2856 }
2857
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002858 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002859
2860 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2861 rule->cond = cond;
2862 rule->srv.name = strdup(args[1]);
2863 LIST_INIT(&rule->list);
2864 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2865 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2866 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002867 else if ((!strcmp(args[0], "force-persist")) ||
2868 (!strcmp(args[0], "ignore-persist"))) {
2869 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002870
2871 if (curproxy == &defproxy) {
2872 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876
2877 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2878 err_code |= ERR_WARN;
2879
Willy Tarreauef6494c2010-01-28 17:12:36 +01002880 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002881 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2882 file, linenum, args[0]);
2883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
2885 }
2886
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002887 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2888 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2889 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892 }
2893
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002894 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2895 * where force-persist is applied.
2896 */
2897 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002898
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002899 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002900 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002901 if (!strcmp(args[0], "force-persist")) {
2902 rule->type = PERSIST_TYPE_FORCE;
2903 } else {
2904 rule->type = PERSIST_TYPE_IGNORE;
2905 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002906 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002907 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002908 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002909 else if (!strcmp(args[0], "stick-table")) {
2910 int myidx = 1;
2911
Emeric Brun32da3c42010-09-23 18:39:19 +02002912 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002913 curproxy->table.type = (unsigned int)-1;
2914 while (*args[myidx]) {
2915 const char *err;
2916
2917 if (strcmp(args[myidx], "size") == 0) {
2918 myidx++;
2919 if (!*(args[myidx])) {
2920 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2921 file, linenum, args[myidx-1]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2926 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2927 file, linenum, *err, args[myidx-1]);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002931 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002932 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002933 else if (strcmp(args[myidx], "peers") == 0) {
2934 myidx++;
2935 if (!*(args[myidx])) {
2936 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2937 file, linenum, args[myidx-1]);
2938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
2940 }
2941 curproxy->table.peers.name = strdup(args[myidx++]);
2942 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002943 else if (strcmp(args[myidx], "expire") == 0) {
2944 myidx++;
2945 if (!*(args[myidx])) {
2946 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2947 file, linenum, args[myidx-1]);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
2951 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2952 if (err) {
2953 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2954 file, linenum, *err, args[myidx-1]);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957 }
2958 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002959 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002960 }
2961 else if (strcmp(args[myidx], "nopurge") == 0) {
2962 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002963 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002964 }
2965 else if (strcmp(args[myidx], "type") == 0) {
2966 myidx++;
2967 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2968 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2969 file, linenum, args[myidx]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002973 /* myidx already points to next arg */
2974 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002975 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002976 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002977 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002978
2979 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002980 nw = args[myidx];
2981 while (*nw) {
2982 /* the "store" keyword supports a comma-separated list */
2983 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002984 sa = NULL; /* store arg */
2985 while (*nw && *nw != ',') {
2986 if (*nw == '(') {
2987 *nw = 0;
2988 sa = ++nw;
2989 while (*nw != ')') {
2990 if (!*nw) {
2991 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2992 file, linenum, args[0], cw);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996 nw++;
2997 }
2998 *nw = '\0';
2999 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003000 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003001 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003002 if (*nw)
3003 *nw++ = '\0';
3004 type = stktable_get_data_type(cw);
3005 if (type < 0) {
3006 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3007 file, linenum, args[0], cw);
3008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
3010 }
Willy Tarreauac782882010-06-20 10:41:54 +02003011
3012 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3013 switch (err) {
3014 case PE_NONE: break;
3015 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003016 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3017 file, linenum, args[0], cw);
3018 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003019 break;
3020
3021 case PE_ARG_MISSING:
3022 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3023 file, linenum, args[0], cw);
3024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026
3027 case PE_ARG_NOT_USED:
3028 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3029 file, linenum, args[0], cw);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032
3033 default:
3034 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3035 file, linenum, args[0], cw);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003038 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003039 }
3040 myidx++;
3041 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003042 else {
3043 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3044 file, linenum, args[myidx]);
3045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 }
3049
3050 if (!curproxy->table.size) {
3051 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3052 file, linenum);
3053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
3055 }
3056
3057 if (curproxy->table.type == (unsigned int)-1) {
3058 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3059 file, linenum);
3060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
3062 }
3063 }
3064 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003065 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003066 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003067 int myidx = 0;
3068 const char *name = NULL;
3069 int flags;
3070
3071 if (curproxy == &defproxy) {
3072 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
3075 }
3076
3077 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3078 err_code |= ERR_WARN;
3079 goto out;
3080 }
3081
3082 myidx++;
3083 if ((strcmp(args[myidx], "store") == 0) ||
3084 (strcmp(args[myidx], "store-request") == 0)) {
3085 myidx++;
3086 flags = STK_IS_STORE;
3087 }
3088 else if (strcmp(args[myidx], "store-response") == 0) {
3089 myidx++;
3090 flags = STK_IS_STORE | STK_ON_RSP;
3091 }
3092 else if (strcmp(args[myidx], "match") == 0) {
3093 myidx++;
3094 flags = STK_IS_MATCH;
3095 }
3096 else if (strcmp(args[myidx], "on") == 0) {
3097 myidx++;
3098 flags = STK_IS_MATCH | STK_IS_STORE;
3099 }
3100 else {
3101 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
3105
3106 if (*(args[myidx]) == 0) {
3107 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
3111
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003112 curproxy->conf.args.ctx = ARGC_STK;
3113 expr = sample_parse_expr(args, &myidx, trash.str, trash.size, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003114 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003115 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119
3120 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003121 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3122 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3123 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003124 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003125 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003126 goto out;
3127 }
3128 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003129 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3130 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3131 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003132 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003133 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003134 goto out;
3135 }
3136 }
3137
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003138 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003139 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003140
Emeric Brunb982a3d2010-01-04 15:45:53 +01003141 if (strcmp(args[myidx], "table") == 0) {
3142 myidx++;
3143 name = args[myidx++];
3144 }
3145
Willy Tarreauef6494c2010-01-28 17:12:36 +01003146 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003147 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3148 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3149 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003150 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003151 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003152 goto out;
3153 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003154 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003155 else if (*(args[myidx])) {
3156 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3157 file, linenum, args[0], args[myidx]);
3158 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003159 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003160 goto out;
3161 }
Emeric Brun97679e72010-09-23 17:56:44 +02003162 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003163 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003164 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003165 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003166
Emeric Brunb982a3d2010-01-04 15:45:53 +01003167 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3168 rule->cond = cond;
3169 rule->expr = expr;
3170 rule->flags = flags;
3171 rule->table.name = name ? strdup(name) : NULL;
3172 LIST_INIT(&rule->list);
3173 if (flags & STK_ON_RSP)
3174 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3175 else
3176 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003179 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003181
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3183 curproxy->uri_auth = NULL; /* we must detach from the default config */
3184
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003185 if (!*args[1]) {
3186 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003187 } else if (!strcmp(args[1], "admin")) {
3188 struct stats_admin_rule *rule;
3189
3190 if (curproxy == &defproxy) {
3191 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
3194 }
3195
3196 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3197 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3198 err_code |= ERR_ALERT | ERR_ABORT;
3199 goto out;
3200 }
3201
3202 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3203 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3204 file, linenum, args[0], args[1]);
3205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
3207 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003208 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3209 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3210 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003215 err_code |= warnif_cond_conflicts(cond,
3216 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3217 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003218
3219 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3220 rule->cond = cond;
3221 LIST_INIT(&rule->list);
3222 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 } else if (!strcmp(args[1], "uri")) {
3224 if (*(args[2]) == 0) {
3225 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3229 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_ABORT;
3231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 }
3233 } else if (!strcmp(args[1], "realm")) {
3234 if (*(args[2]) == 0) {
3235 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_ALERT | ERR_ABORT;
3241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003243 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003244 unsigned interval;
3245
3246 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3247 if (err) {
3248 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3249 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003252 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3253 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_ABORT;
3255 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003256 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003257 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003258 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003259
3260 if (curproxy == &defproxy) {
3261 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
3264 }
3265
3266 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3267 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3268 err_code |= ERR_ALERT | ERR_ABORT;
3269 goto out;
3270 }
3271
Willy Tarreauff011f22011-01-06 17:51:27 +01003272 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3273 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003274 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3275 file, linenum, args[0]);
3276 err_code |= ERR_WARN;
3277 }
3278
Willy Tarreauff011f22011-01-06 17:51:27 +01003279 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003280
Willy Tarreauff011f22011-01-06 17:51:27 +01003281 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003282 err_code |= ERR_ALERT | ERR_ABORT;
3283 goto out;
3284 }
3285
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003286 err_code |= warnif_cond_conflicts(rule->cond,
3287 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3288 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003289 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003290
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 } else if (!strcmp(args[1], "auth")) {
3292 if (*(args[2]) == 0) {
3293 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_ABORT;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
3301 } else if (!strcmp(args[1], "scope")) {
3302 if (*(args[2]) == 0) {
3303 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3307 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_ABORT;
3309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
3311 } else if (!strcmp(args[1], "enable")) {
3312 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_ALERT | ERR_ABORT;
3315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003317 } else if (!strcmp(args[1], "hide-version")) {
3318 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_ABORT;
3321 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003322 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003323 } else if (!strcmp(args[1], "show-legends")) {
3324 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3325 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3326 err_code |= ERR_ALERT | ERR_ABORT;
3327 goto out;
3328 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003329 } else if (!strcmp(args[1], "show-node")) {
3330
3331 if (*args[2]) {
3332 int i;
3333 char c;
3334
3335 for (i=0; args[2][i]; i++) {
3336 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003337 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3338 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003339 break;
3340 }
3341
3342 if (!i || args[2][i]) {
3343 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3344 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3345 file, linenum, args[0], args[1]);
3346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
3348 }
3349 }
3350
3351 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3352 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3353 err_code |= ERR_ALERT | ERR_ABORT;
3354 goto out;
3355 }
3356 } else if (!strcmp(args[1], "show-desc")) {
3357 char *desc = NULL;
3358
3359 if (*args[2]) {
3360 int i, len=0;
3361 char *d;
3362
3363 for(i=2; *args[i]; i++)
3364 len += strlen(args[i])+1;
3365
3366 desc = d = (char *)calloc(1, len);
3367
3368 d += sprintf(d, "%s", args[2]);
3369 for(i=3; *args[i]; i++)
3370 d += sprintf(d, " %s", args[i]);
3371 }
3372
3373 if (!*args[2] && !global.desc)
3374 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3375 file, linenum, args[1]);
3376 else {
3377 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3378 free(desc);
3379 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3380 err_code |= ERR_ALERT | ERR_ABORT;
3381 goto out;
3382 }
3383 free(desc);
3384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003386stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003387 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003388 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 }
3392 }
3393 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003394 int optnum;
3395
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003396 if (*(args[1]) == '\0') {
3397 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3398 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003402
3403 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3404 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003405 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3406 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3407 file, linenum, cfg_opts[optnum].name);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
Willy Tarreau93893792009-07-23 13:19:11 +02003411 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3412 err_code |= ERR_WARN;
3413 goto out;
3414 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003415
Willy Tarreau3842f002009-06-14 11:39:52 +02003416 curproxy->no_options &= ~cfg_opts[optnum].val;
3417 curproxy->options &= ~cfg_opts[optnum].val;
3418
3419 switch (kwm) {
3420 case KWM_STD:
3421 curproxy->options |= cfg_opts[optnum].val;
3422 break;
3423 case KWM_NO:
3424 curproxy->no_options |= cfg_opts[optnum].val;
3425 break;
3426 case KWM_DEF: /* already cleared */
3427 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003428 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003429
Willy Tarreau93893792009-07-23 13:19:11 +02003430 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003431 }
3432 }
3433
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003434 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3435 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003436 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3437 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3438 file, linenum, cfg_opts2[optnum].name);
3439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
3441 }
Willy Tarreau93893792009-07-23 13:19:11 +02003442 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3443 err_code |= ERR_WARN;
3444 goto out;
3445 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003446
Willy Tarreau3842f002009-06-14 11:39:52 +02003447 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3448 curproxy->options2 &= ~cfg_opts2[optnum].val;
3449
3450 switch (kwm) {
3451 case KWM_STD:
3452 curproxy->options2 |= cfg_opts2[optnum].val;
3453 break;
3454 case KWM_NO:
3455 curproxy->no_options2 |= cfg_opts2[optnum].val;
3456 break;
3457 case KWM_DEF: /* already cleared */
3458 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003459 }
Willy Tarreau93893792009-07-23 13:19:11 +02003460 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003461 }
3462 }
3463
Willy Tarreau3842f002009-06-14 11:39:52 +02003464 if (kwm != KWM_STD) {
3465 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003466 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003469 }
3470
Emeric Brun3a058f32009-06-30 18:26:00 +02003471 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003472 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003474 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003475 if (*(args[2]) != '\0') {
3476 if (!strcmp(args[2], "clf")) {
3477 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003478 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003479 } else {
3480 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003483 }
3484 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003485 if (curproxy->conf.logformat_string != default_http_log_format &&
3486 curproxy->conf.logformat_string != default_tcp_log_format &&
3487 curproxy->conf.logformat_string != clf_http_log_format)
3488 free(curproxy->conf.logformat_string);
3489 curproxy->conf.logformat_string = logformat;
3490
3491 free(curproxy->conf.lfs_file);
3492 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3493 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003494 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003495 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003497 if (curproxy->conf.logformat_string != default_http_log_format &&
3498 curproxy->conf.logformat_string != default_tcp_log_format &&
3499 curproxy->conf.logformat_string != clf_http_log_format)
3500 free(curproxy->conf.logformat_string);
3501 curproxy->conf.logformat_string = default_tcp_log_format;
3502
3503 free(curproxy->conf.lfs_file);
3504 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3505 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 else if (!strcmp(args[1], "tcpka")) {
3508 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003509 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003511
3512 if (curproxy->cap & PR_CAP_FE)
3513 curproxy->options |= PR_O_TCP_CLI_KA;
3514 if (curproxy->cap & PR_CAP_BE)
3515 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 }
3517 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003518 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_WARN;
3520
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003522 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003523 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003524 curproxy->options2 &= ~PR_O2_CHK_ANY;
3525 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003526 if (!*args[2]) { /* no argument */
3527 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3528 curproxy->check_len = strlen(DEF_CHECK_REQ);
3529 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003530 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 curproxy->check_req = (char *)malloc(reqlen);
3532 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003533 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003535 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 if (*args[4])
3537 reqlen += strlen(args[4]);
3538 else
3539 reqlen += strlen("HTTP/1.0");
3540
3541 curproxy->check_req = (char *)malloc(reqlen);
3542 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003543 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003545 }
3546 else if (!strcmp(args[1], "ssl-hello-chk")) {
3547 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003548 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003550
Willy Tarreaua534fea2008-08-03 12:19:50 +02003551 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003552 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003553 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003554 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 }
Willy Tarreau23677902007-05-08 23:50:35 +02003556 else if (!strcmp(args[1], "smtpchk")) {
3557 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003558 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003559 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003560 curproxy->options2 &= ~PR_O2_CHK_ANY;
3561 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003562
3563 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3564 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3565 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3566 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3567 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3568 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3569 curproxy->check_req = (char *)malloc(reqlen);
3570 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3571 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3572 } else {
3573 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3574 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3575 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3576 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3577 }
3578 }
3579 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003580 else if (!strcmp(args[1], "pgsql-check")) {
3581 /* use PostgreSQL request to check servers' health */
3582 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3583 err_code |= ERR_WARN;
3584
3585 free(curproxy->check_req);
3586 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003587 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003588 curproxy->options2 |= PR_O2_PGSQL_CHK;
3589
3590 if (*(args[2])) {
3591 int cur_arg = 2;
3592
3593 while (*(args[cur_arg])) {
3594 if (strcmp(args[cur_arg], "user") == 0) {
3595 char * packet;
3596 uint32_t packet_len;
3597 uint32_t pv;
3598
3599 /* suboption header - needs additional argument for it */
3600 if (*(args[cur_arg+1]) == 0) {
3601 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3602 file, linenum, args[0], args[1], args[cur_arg]);
3603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
3605 }
3606
3607 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3608 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3609 pv = htonl(0x30000); /* protocol version 3.0 */
3610
3611 packet = (char*) calloc(1, packet_len);
3612
3613 memcpy(packet + 4, &pv, 4);
3614
3615 /* copy "user" */
3616 memcpy(packet + 8, "user", 4);
3617
3618 /* copy username */
3619 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3620
3621 free(curproxy->check_req);
3622 curproxy->check_req = packet;
3623 curproxy->check_len = packet_len;
3624
3625 packet_len = htonl(packet_len);
3626 memcpy(packet, &packet_len, 4);
3627 cur_arg += 2;
3628 } else {
3629 /* unknown suboption - catchall */
3630 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3631 file, linenum, args[0], args[1]);
3632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
3634 }
3635 } /* end while loop */
3636 }
3637 }
3638
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003639 else if (!strcmp(args[1], "redis-check")) {
3640 /* use REDIS PING request to check servers' health */
3641 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3642 err_code |= ERR_WARN;
3643
3644 free(curproxy->check_req);
3645 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003646 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003647 curproxy->options2 |= PR_O2_REDIS_CHK;
3648
3649 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3650 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3651 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3652 }
3653
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003654 else if (!strcmp(args[1], "mysql-check")) {
3655 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003656 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3657 err_code |= ERR_WARN;
3658
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003659 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003660 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003661 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003662 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003663
3664 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3665 * const char mysql40_client_auth_pkt[] = {
3666 * "\x0e\x00\x00" // packet length
3667 * "\x01" // packet number
3668 * "\x00\x00" // client capabilities
3669 * "\x00\x00\x01" // max packet
3670 * "haproxy\x00" // username (null terminated string)
3671 * "\x00" // filler (always 0x00)
3672 * "\x01\x00\x00" // packet length
3673 * "\x00" // packet number
3674 * "\x01" // COM_QUIT command
3675 * };
3676 */
3677
3678 if (*(args[2])) {
3679 int cur_arg = 2;
3680
3681 while (*(args[cur_arg])) {
3682 if (strcmp(args[cur_arg], "user") == 0) {
3683 char *mysqluser;
3684 int packetlen, reqlen, userlen;
3685
3686 /* suboption header - needs additional argument for it */
3687 if (*(args[cur_arg+1]) == 0) {
3688 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3689 file, linenum, args[0], args[1], args[cur_arg]);
3690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
3692 }
3693 mysqluser = args[cur_arg + 1];
3694 userlen = strlen(mysqluser);
3695 packetlen = userlen + 7;
3696 reqlen = packetlen + 9;
3697
3698 free(curproxy->check_req);
3699 curproxy->check_req = (char *)calloc(1, reqlen);
3700 curproxy->check_len = reqlen;
3701
3702 snprintf(curproxy->check_req, 4, "%c%c%c",
3703 ((unsigned char) packetlen & 0xff),
3704 ((unsigned char) (packetlen >> 8) & 0xff),
3705 ((unsigned char) (packetlen >> 16) & 0xff));
3706
3707 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003708 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003709 curproxy->check_req[8] = 1;
3710 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3711 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3712 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3713 cur_arg += 2;
3714 } else {
3715 /* unknown suboption - catchall */
3716 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3717 file, linenum, args[0], args[1]);
3718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
3720 }
3721 } /* end while loop */
3722 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003723 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003724 else if (!strcmp(args[1], "ldap-check")) {
3725 /* use LDAP request to check servers' health */
3726 free(curproxy->check_req);
3727 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003728 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003729 curproxy->options2 |= PR_O2_LDAP_CHK;
3730
3731 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3732 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3733 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3734 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003735 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003736 int cur_arg;
3737
3738 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3739 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003740 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003741
Willy Tarreau87cf5142011-08-19 22:57:24 +02003742 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003743
3744 free(curproxy->fwdfor_hdr_name);
3745 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3746 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3747
3748 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3749 cur_arg = 2;
3750 while (*(args[cur_arg])) {
3751 if (!strcmp(args[cur_arg], "except")) {
3752 /* suboption except - needs additional argument for it */
3753 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3754 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3755 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003758 }
3759 /* flush useless bits */
3760 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003761 cur_arg += 2;
3762 } else if (!strcmp(args[cur_arg], "header")) {
3763 /* suboption header - needs additional argument for it */
3764 if (*(args[cur_arg+1]) == 0) {
3765 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3766 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003769 }
3770 free(curproxy->fwdfor_hdr_name);
3771 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3772 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3773 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003774 } else if (!strcmp(args[cur_arg], "if-none")) {
3775 curproxy->options &= ~PR_O_FF_ALWAYS;
3776 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003777 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003778 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003779 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003780 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003783 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003784 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003785 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003786 else if (!strcmp(args[1], "originalto")) {
3787 int cur_arg;
3788
3789 /* insert x-original-to field, but not for the IP address listed as an except.
3790 * set default options (ie: bitfield, header name, etc)
3791 */
3792
3793 curproxy->options |= PR_O_ORGTO;
3794
3795 free(curproxy->orgto_hdr_name);
3796 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3797 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3798
Willy Tarreau87cf5142011-08-19 22:57:24 +02003799 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003800 cur_arg = 2;
3801 while (*(args[cur_arg])) {
3802 if (!strcmp(args[cur_arg], "except")) {
3803 /* suboption except - needs additional argument for it */
3804 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3805 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3806 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003809 }
3810 /* flush useless bits */
3811 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3812 cur_arg += 2;
3813 } else if (!strcmp(args[cur_arg], "header")) {
3814 /* suboption header - needs additional argument for it */
3815 if (*(args[cur_arg+1]) == 0) {
3816 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3817 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003820 }
3821 free(curproxy->orgto_hdr_name);
3822 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3823 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3824 cur_arg += 2;
3825 } else {
3826 /* unknown suboption - catchall */
3827 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3828 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003831 }
3832 } /* end while loop */
3833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 else {
3835 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 }
Willy Tarreau93893792009-07-23 13:19:11 +02003839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003841 else if (!strcmp(args[0], "default_backend")) {
3842 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003843 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003844
3845 if (*(args[1]) == 0) {
3846 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003849 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003850 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003851 curproxy->defbe.name = strdup(args[1]);
3852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003856
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003857 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3858 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 /* enable reconnections to dispatch */
3861 curproxy->options |= PR_O_REDISP;
3862 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003863 else if (!strcmp(args[0], "http-check")) {
3864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003866
3867 if (strcmp(args[1], "disable-on-404") == 0) {
3868 /* enable a graceful server shutdown on an HTTP 404 response */
3869 curproxy->options |= PR_O_DISABLE404;
3870 }
Willy Tarreauef781042010-01-27 11:53:01 +01003871 else if (strcmp(args[1], "send-state") == 0) {
3872 /* enable emission of the apparent state of a server in HTTP checks */
3873 curproxy->options2 |= PR_O2_CHK_SNDST;
3874 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003875 else if (strcmp(args[1], "expect") == 0) {
3876 const char *ptr_arg;
3877 int cur_arg;
3878
3879 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3880 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3881 err_code |= ERR_ALERT | ERR_FATAL;
3882 goto out;
3883 }
3884
3885 cur_arg = 2;
3886 /* consider exclamation marks, sole or at the beginning of a word */
3887 while (*(ptr_arg = args[cur_arg])) {
3888 while (*ptr_arg == '!') {
3889 curproxy->options2 ^= PR_O2_EXP_INV;
3890 ptr_arg++;
3891 }
3892 if (*ptr_arg)
3893 break;
3894 cur_arg++;
3895 }
3896 /* now ptr_arg points to the beginning of a word past any possible
3897 * exclamation mark, and cur_arg is the argument which holds this word.
3898 */
3899 if (strcmp(ptr_arg, "status") == 0) {
3900 if (!*(args[cur_arg + 1])) {
3901 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3902 file, linenum, args[0], args[1], ptr_arg);
3903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
3905 }
3906 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003907 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003908 curproxy->expect_str = strdup(args[cur_arg + 1]);
3909 }
3910 else if (strcmp(ptr_arg, "string") == 0) {
3911 if (!*(args[cur_arg + 1])) {
3912 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3913 file, linenum, args[0], args[1], ptr_arg);
3914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
3916 }
3917 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003918 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003919 curproxy->expect_str = strdup(args[cur_arg + 1]);
3920 }
3921 else if (strcmp(ptr_arg, "rstatus") == 0) {
3922 if (!*(args[cur_arg + 1])) {
3923 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3924 file, linenum, args[0], args[1], ptr_arg);
3925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
3927 }
3928 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003929 free(curproxy->expect_str);
3930 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3931 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003932 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3933 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3934 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3935 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
3938 }
3939 }
3940 else if (strcmp(ptr_arg, "rstring") == 0) {
3941 if (!*(args[cur_arg + 1])) {
3942 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3943 file, linenum, args[0], args[1], ptr_arg);
3944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
3946 }
3947 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003948 free(curproxy->expect_str);
3949 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3950 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003951 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3952 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3953 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3954 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
3958 }
3959 else {
3960 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3961 file, linenum, args[0], args[1], ptr_arg);
3962 err_code |= ERR_ALERT | ERR_FATAL;
3963 goto out;
3964 }
3965 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003966 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003967 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 +02003968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003970 }
3971 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003972 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003973 if (curproxy == &defproxy) {
3974 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003977 }
3978
Willy Tarreaub80c2302007-11-30 20:51:32 +01003979 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003981
3982 if (strcmp(args[1], "fail") == 0) {
3983 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003984 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003985 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3986 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003989 }
3990
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003991 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3992 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3993 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003996 }
3997 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3998 }
3999 else {
4000 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004003 }
4004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005#ifdef TPROXY
4006 else if (!strcmp(args[0], "transparent")) {
4007 /* enable transparent proxy connections */
4008 curproxy->options |= PR_O_TRANSP;
4009 }
4010#endif
4011 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004012 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004013 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004014
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 if (*(args[1]) == 0) {
4016 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 }
4020 curproxy->maxconn = atol(args[1]);
4021 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004022 else if (!strcmp(args[0], "backlog")) { /* backlog */
4023 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004024 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004025
4026 if (*(args[1]) == 0) {
4027 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004030 }
4031 curproxy->backlog = atol(args[1]);
4032 }
Willy Tarreau86034312006-12-29 00:10:33 +01004033 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004034 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004036
Willy Tarreau86034312006-12-29 00:10:33 +01004037 if (*(args[1]) == 0) {
4038 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004041 }
4042 curproxy->fullconn = atol(args[1]);
4043 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4045 if (*(args[1]) == 0) {
4046 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004050 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4051 if (err) {
4052 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4053 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004056 }
4057 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 }
4059 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004060 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004061 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004062 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004063
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 if (curproxy == &defproxy) {
4065 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004069 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004070 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004071
Willy Tarreau902636f2013-03-10 19:44:48 +01004072 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004073 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004074 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004075 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004076 goto out;
4077 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004078
4079 proto = protocol_by_family(sk->ss_family);
4080 if (!proto || !proto->connect) {
4081 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4082 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
4085 }
4086
4087 if (port1 != port2) {
4088 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4089 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004093
4094 if (!port1) {
4095 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4096 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004100
Willy Tarreaud5191e72010-02-09 20:50:45 +01004101 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004102 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004103 }
4104 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004105 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004107
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004108 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4109 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004114 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004115 /**
4116 * The syntax for hash-type config element is
4117 * hash-type {map-based|consistent} [[<algo>] avalanche]
4118 *
4119 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4120 */
4121 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004122
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004123 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4124 err_code |= ERR_WARN;
4125
4126 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004127 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4128 }
4129 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004130 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4131 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004132 else if (strcmp(args[1], "avalanche") == 0) {
4133 Alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004136 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004137 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004138 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
4141 }
Bhaskar98634f02013-10-29 23:30:51 -04004142
4143 /* set the hash function to use */
4144 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004145 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004146 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004147
4148 /* if consistent with no argument, then avalanche modifier is also applied */
4149 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4150 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004151 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004152 /* set the hash function */
4153 if (!strcmp(args[2], "sdbm")) {
4154 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4155 }
4156 else if (!strcmp(args[2], "djb2")) {
4157 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004158 } else if (!strcmp(args[2], "wt6")) {
4159 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004160 }
4161 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004162 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
4165 }
4166
4167 /* set the hash modifier */
4168 if (!strcmp(args[3], "avalanche")) {
4169 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4170 }
4171 else if (*args[3]) {
4172 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
4175 }
Bhaskar98634f02013-10-29 23:30:51 -04004176 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004177 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004178 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004180 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004181 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004183 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004184 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004188 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004189 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190
4191 if (!*args[2]) {
4192 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004197
4198 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004199 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004200 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4201 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004204 }
4205
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004206 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004207 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004208 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004209 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004210
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004211 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4212 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4213 err_code |= ERR_ALERT | ERR_ABORT;
4214 goto out;
4215 }
4216
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004217 /* the servers are linked backwards first */
4218 newsrv->next = curproxy->srv;
4219 curproxy->srv = newsrv;
4220 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004221 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004222 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004224 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004225 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004226 LIST_INIT(&newsrv->pendconns);
4227 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004228 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004229 newsrv->state = SRV_RUNNING; /* early server setup */
4230 newsrv->last_change = now.tv_sec;
4231 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004232
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004233 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004234 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004235 * - IP: => port=+0, relative
4236 * - IP:N => port=N, absolute
4237 * - IP:+N => port=+N, relative
4238 * - IP:-N => port=-N, relative
4239 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004240 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004241 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004242 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004243 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004244 goto out;
4245 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004246
4247 proto = protocol_by_family(sk->ss_family);
4248 if (!proto || !proto->connect) {
4249 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4250 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
4253 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004254
4255 if (!port1 || !port2) {
4256 /* no port specified, +offset, -offset */
4257 newsrv->state |= SRV_MAPPORTS;
4258 }
4259 else if (port1 != port2) {
4260 /* port range */
4261 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4262 file, linenum, args[0], args[1], args[2]);
4263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265 }
4266 else {
4267 /* used by checks */
4268 realport = port1;
4269 }
4270
Willy Tarreaud5191e72010-02-09 20:50:45 +01004271 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004272 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4273 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004274
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004275 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004276 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4277 file, linenum, newsrv->addr.ss_family, args[2]);
4278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
4280 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004281
Simon Hormand60d6912013-11-25 10:46:36 +09004282 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004283 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004284 newsrv->check.inter = curproxy->defsrv.check.inter;
4285 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4286 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004287 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4288 newsrv->agent.port = curproxy->defsrv.agent.port;
4289 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4290 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4291 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004292 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4293 newsrv->minconn = curproxy->defsrv.minconn;
4294 newsrv->maxconn = curproxy->defsrv.maxconn;
4295 newsrv->slowstart = curproxy->defsrv.slowstart;
4296 newsrv->onerror = curproxy->defsrv.onerror;
4297 newsrv->consecutive_errors_limit
4298 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004299#ifdef OPENSSL
4300 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4301#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004302 newsrv->uweight = newsrv->iweight
4303 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004304
Simon Horman69d29f92013-02-23 15:14:19 +09004305 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004306 newsrv->check.rise = curproxy->defsrv.check.rise;
4307 newsrv->check.fall = curproxy->defsrv.check.fall;
4308 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004309 newsrv->check.server = newsrv;
4310
Simon Hormand60d6912013-11-25 10:46:36 +09004311 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004312 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4313 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4314 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004315 newsrv->agent.server = newsrv;
4316
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004317 cur_arg = 3;
4318 } else {
4319 newsrv = &curproxy->defsrv;
4320 cur_arg = 1;
4321 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004322
Willy Tarreaubaaee002006-06-26 02:48:02 +02004323 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004324 if (!strcmp(args[cur_arg], "agent-check")) {
4325 global.maxsock++;
4326 do_agent = 1;
4327 cur_arg += 1;
4328 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4329 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4330 if (err) {
4331 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4332 file, linenum, *err, newsrv->id);
4333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
4335 }
4336 if (val <= 0) {
4337 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4338 file, linenum, val, args[cur_arg], newsrv->id);
4339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
4341 }
4342 newsrv->agent.inter = val;
4343 cur_arg += 2;
4344 }
4345 else if (!strcmp(args[cur_arg], "agent-port")) {
4346 global.maxsock++;
4347 newsrv->agent.port = atol(args[cur_arg + 1]);
4348 cur_arg += 2;
4349 }
4350 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004351 newsrv->cookie = strdup(args[cur_arg + 1]);
4352 newsrv->cklen = strlen(args[cur_arg + 1]);
4353 cur_arg += 2;
4354 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004355 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004356 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4357 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4358 cur_arg += 2;
4359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004360 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004361 if (!*args[cur_arg + 1]) {
4362 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4363 file, linenum, args[cur_arg]);
4364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
4366 }
4367
Simon Horman58c32972013-11-25 10:46:38 +09004368 newsrv->check.rise = atol(args[cur_arg + 1]);
4369 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004370 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4371 file, linenum, args[cur_arg]);
4372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
4374 }
4375
Simon Horman125d0992013-02-24 17:23:38 +09004376 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004377 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004378 cur_arg += 2;
4379 }
4380 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004381 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004382
4383 if (!*args[cur_arg + 1]) {
4384 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4385 file, linenum, args[cur_arg]);
4386 err_code |= ERR_ALERT | ERR_FATAL;
4387 goto out;
4388 }
4389
Simon Horman58c32972013-11-25 10:46:38 +09004390 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004391 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4392 file, linenum, args[cur_arg]);
4393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
4395 }
4396
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397 cur_arg += 2;
4398 }
4399 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004400 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4401 if (err) {
4402 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4403 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004406 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004407 if (val <= 0) {
4408 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4409 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004412 }
Simon Horman66183002013-02-23 10:16:43 +09004413 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 cur_arg += 2;
4415 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004416 else if (!strcmp(args[cur_arg], "fastinter")) {
4417 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4418 if (err) {
4419 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4420 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004421 err_code |= ERR_ALERT | ERR_FATAL;
4422 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004423 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004424 if (val <= 0) {
4425 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4426 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004429 }
Simon Horman66183002013-02-23 10:16:43 +09004430 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004431 cur_arg += 2;
4432 }
4433 else if (!strcmp(args[cur_arg], "downinter")) {
4434 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4435 if (err) {
4436 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4437 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004440 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004441 if (val <= 0) {
4442 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4443 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004446 }
Simon Horman66183002013-02-23 10:16:43 +09004447 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004448 cur_arg += 2;
4449 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004450 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004451 struct sockaddr_storage *sk;
4452 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004453 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004454
Willy Tarreau902636f2013-03-10 19:44:48 +01004455 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004456 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004457 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004458 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004459 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004460 goto out;
4461 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004462
4463 proto = protocol_by_family(sk->ss_family);
4464 if (!proto || !proto->connect) {
4465 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004466 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
4469 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004470
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004471 if (port1 != port2) {
4472 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4473 file, linenum, args[cur_arg], args[cur_arg + 1]);
4474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
4476 }
4477
Simon Horman66183002013-02-23 10:16:43 +09004478 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004479 cur_arg += 2;
4480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004482 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004483 cur_arg += 2;
4484 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004485 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 newsrv->state |= SRV_BACKUP;
4487 cur_arg ++;
4488 }
Simon Hormanfa461682011-06-25 09:39:49 +09004489 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4490 newsrv->state |= SRV_NON_STICK;
4491 cur_arg ++;
4492 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004493 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4494 newsrv->state |= SRV_SEND_PROXY;
4495 cur_arg ++;
4496 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004497 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4498 newsrv->check.send_proxy = 1;
4499 cur_arg ++;
4500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 else if (!strcmp(args[cur_arg], "weight")) {
4502 int w;
4503 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004504 if (w < 0 || w > SRV_UWGHT_MAX) {
4505 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4506 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004510 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 cur_arg += 2;
4512 }
4513 else if (!strcmp(args[cur_arg], "minconn")) {
4514 newsrv->minconn = atol(args[cur_arg + 1]);
4515 cur_arg += 2;
4516 }
4517 else if (!strcmp(args[cur_arg], "maxconn")) {
4518 newsrv->maxconn = atol(args[cur_arg + 1]);
4519 cur_arg += 2;
4520 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004521 else if (!strcmp(args[cur_arg], "maxqueue")) {
4522 newsrv->maxqueue = atol(args[cur_arg + 1]);
4523 cur_arg += 2;
4524 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004525 else if (!strcmp(args[cur_arg], "slowstart")) {
4526 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004527 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004528 if (err) {
4529 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4530 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004531 err_code |= ERR_ALERT | ERR_FATAL;
4532 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004533 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004534 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004535 cur_arg += 2;
4536 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004537 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004538
4539 if (!*args[cur_arg + 1]) {
4540 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4541 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004544 }
4545
4546 newsrv->trackit = strdup(args[cur_arg + 1]);
4547
4548 cur_arg += 2;
4549 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004550 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551 global.maxsock++;
4552 do_check = 1;
4553 cur_arg += 1;
4554 }
Willy Tarreau96839092010-03-29 10:02:24 +02004555 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4556 newsrv->state |= SRV_MAINTAIN;
4557 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09004558 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004559 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004560 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004561 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004562 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004563 if (!strcmp(args[cur_arg + 1], "none"))
4564 newsrv->observe = HANA_OBS_NONE;
4565 else if (!strcmp(args[cur_arg + 1], "layer4"))
4566 newsrv->observe = HANA_OBS_LAYER4;
4567 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4568 if (curproxy->mode != PR_MODE_HTTP) {
4569 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4570 file, linenum, args[cur_arg + 1]);
4571 err_code |= ERR_ALERT;
4572 }
4573 newsrv->observe = HANA_OBS_LAYER7;
4574 }
4575 else {
4576 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004577 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004578 file, linenum, args[cur_arg], args[cur_arg + 1]);
4579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
4581 }
4582
4583 cur_arg += 2;
4584 }
4585 else if (!strcmp(args[cur_arg], "on-error")) {
4586 if (!strcmp(args[cur_arg + 1], "fastinter"))
4587 newsrv->onerror = HANA_ONERR_FASTINTER;
4588 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4589 newsrv->onerror = HANA_ONERR_FAILCHK;
4590 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4591 newsrv->onerror = HANA_ONERR_SUDDTH;
4592 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4593 newsrv->onerror = HANA_ONERR_MARKDWN;
4594 else {
4595 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004596 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004597 file, linenum, args[cur_arg], args[cur_arg + 1]);
4598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
4600 }
4601
4602 cur_arg += 2;
4603 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004604 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4605 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4606 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4607 else {
4608 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4609 file, linenum, args[cur_arg], args[cur_arg + 1]);
4610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
4612 }
4613
4614 cur_arg += 2;
4615 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004616 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4617 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4618 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4619 else {
4620 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4621 file, linenum, args[cur_arg], args[cur_arg + 1]);
4622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
4624 }
4625
4626 cur_arg += 2;
4627 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004628 else if (!strcmp(args[cur_arg], "error-limit")) {
4629 if (!*args[cur_arg + 1]) {
4630 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4631 file, linenum, args[cur_arg]);
4632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
4635
4636 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4637
4638 if (newsrv->consecutive_errors_limit <= 0) {
4639 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4640 file, linenum, args[cur_arg]);
4641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004644 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004645 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004646 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004647 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004648 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004649 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004650
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004652 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4653 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004656 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004657
Willy Tarreauef9a3602012-12-08 22:29:20 +01004658 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004659 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004660 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004661 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004662 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004663 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004664 goto out;
4665 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004666
4667 proto = protocol_by_family(sk->ss_family);
4668 if (!proto || !proto->connect) {
4669 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4670 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004671 err_code |= ERR_ALERT | ERR_FATAL;
4672 goto out;
4673 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004674
Willy Tarreauef9a3602012-12-08 22:29:20 +01004675 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004676
4677 if (port_low != port_high) {
4678 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004679
4680 if (!port_low || !port_high) {
4681 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4682 file, linenum, args[cur_arg], args[cur_arg + 1]);
4683 err_code |= ERR_ALERT | ERR_FATAL;
4684 goto out;
4685 }
4686
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004687 if (port_low <= 0 || port_low > 65535 ||
4688 port_high <= 0 || port_high > 65535 ||
4689 port_low > port_high) {
4690 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4691 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004692 err_code |= ERR_ALERT | ERR_FATAL;
4693 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004694 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004695 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4696 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4697 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004698 }
4699
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004701 while (*(args[cur_arg])) {
4702 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004703#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4704#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004705 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004706 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4707 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004710 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004711#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004712 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004713 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004714 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004717 }
4718 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004719 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4720 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004721 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004722 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4723 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004724 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4725 char *name, *end;
4726
4727 name = args[cur_arg+1] + 7;
4728 while (isspace(*name))
4729 name++;
4730
4731 end = name;
4732 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4733 end++;
4734
Willy Tarreauef9a3602012-12-08 22:29:20 +01004735 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4736 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4737 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4738 newsrv->conn_src.bind_hdr_len = end - name;
4739 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4740 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4741 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004742
4743 /* now look for an occurrence number */
4744 while (isspace(*end))
4745 end++;
4746 if (*end == ',') {
4747 end++;
4748 name = end;
4749 if (*end == '-')
4750 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004751 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004752 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004753 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004754 }
4755
Willy Tarreauef9a3602012-12-08 22:29:20 +01004756 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004757 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4758 " occurrences values smaller than %d.\n",
4759 file, linenum, MAX_HDR_HISTORY);
4760 err_code |= ERR_ALERT | ERR_FATAL;
4761 goto out;
4762 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004763 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004764 struct sockaddr_storage *sk;
4765 int port1, port2;
4766
Willy Tarreau902636f2013-03-10 19:44:48 +01004767 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004768 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004769 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004770 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004771 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004772 goto out;
4773 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004774
4775 proto = protocol_by_family(sk->ss_family);
4776 if (!proto || !proto->connect) {
4777 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4778 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004779 err_code |= ERR_ALERT | ERR_FATAL;
4780 goto out;
4781 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004782
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004783 if (port1 != port2) {
4784 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4785 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004786 err_code |= ERR_ALERT | ERR_FATAL;
4787 goto out;
4788 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004789 newsrv->conn_src.tproxy_addr = *sk;
4790 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004791 }
4792 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004793#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004794 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004795#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004796 cur_arg += 2;
4797 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004798#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004799 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004800 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004803#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004804 } /* "usesrc" */
4805
4806 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4807#ifdef SO_BINDTODEVICE
4808 if (!*args[cur_arg + 1]) {
4809 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4810 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004813 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004814 free(newsrv->conn_src.iface_name);
4815 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4816 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004817 global.last_checks |= LSTCHK_NETADM;
4818#else
4819 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4820 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004823#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004824 cur_arg += 2;
4825 continue;
4826 }
4827 /* this keyword in not an option of "source" */
4828 break;
4829 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004830 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004831 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004832 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4833 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004836 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004837 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004838 static int srv_dumped;
4839 struct srv_kw *kw;
4840 char *err;
4841
4842 kw = srv_find_kw(args[cur_arg]);
4843 if (kw) {
4844 char *err = NULL;
4845 int code;
4846
4847 if (!kw->parse) {
4848 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4849 file, linenum, args[0], args[1], args[cur_arg]);
4850 cur_arg += 1 + kw->skip ;
4851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
4853 }
4854
4855 if (defsrv && !kw->default_ok) {
4856 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4857 file, linenum, args[0], args[1], args[cur_arg]);
4858 cur_arg += 1 + kw->skip ;
4859 err_code |= ERR_ALERT;
4860 continue;
4861 }
4862
4863 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4864 err_code |= code;
4865
4866 if (code) {
4867 if (err && *err) {
4868 indent_msg(&err, 2);
4869 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4870 }
4871 else
4872 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4873 file, linenum, args[0], args[1], args[cur_arg]);
4874 if (code & ERR_FATAL) {
4875 free(err);
4876 cur_arg += 1 + kw->skip;
4877 goto out;
4878 }
4879 }
4880 free(err);
4881 cur_arg += 1 + kw->skip;
4882 continue;
4883 }
4884
4885 err = NULL;
4886 if (!srv_dumped) {
4887 srv_dump_kws(&err);
4888 indent_msg(&err, 4);
4889 srv_dumped = 1;
4890 }
4891
4892 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4893 file, linenum, args[0], args[1], args[cur_arg],
4894 err ? " Registered keywords :" : "", err ? err : "");
4895 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004896
Willy Tarreau93893792009-07-23 13:19:11 +02004897 err_code |= ERR_ALERT | ERR_FATAL;
4898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 }
4900 }
4901
Simon Horman8c3d0be2013-11-25 10:46:40 +09004902 /* Set initial drain state using now-configured weight */
4903 set_server_drain_state(newsrv);
4904
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09004906 int ret;
4907
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004908 if (newsrv->trackit) {
4909 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4910 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004913 }
4914
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004915 /* If neither a port nor an addr was specified and no check transport
4916 * layer is forced, then the transport layer used by the checks is the
4917 * same as for the production traffic. Otherwise we use raw_sock by
4918 * default, unless one is specified.
4919 */
Simon Horman66183002013-02-23 10:16:43 +09004920 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004921#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004922 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004923#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004924 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4925 }
Simon Horman66183002013-02-23 10:16:43 +09004926 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004927 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09004928 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004929
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004930 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004931 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004932
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004933 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004934 /* not yet valid, because no port was set on
4935 * the server either. We'll check if we have
4936 * a known port on the first listener.
4937 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004938 struct listener *l;
4939
4940 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004941 newsrv->check.port = get_host_port(&l->addr);
4942 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004943 break;
4944 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004945 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004946 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4948 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004952
Simon Horman69d29f92013-02-23 15:14:19 +09004953 ret = init_check(&newsrv->check,
4954 curproxy->options2 & PR_O2_CHK_ANY,
4955 file, linenum);
4956 if (ret) {
4957 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004958 goto out;
4959 }
4960
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 newsrv->state |= SRV_CHECKED;
4962 }
4963
Simon Hormand60d6912013-11-25 10:46:36 +09004964 if (do_agent) {
4965 int ret;
4966
4967 if (!newsrv->agent.port) {
4968 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
4969 file, linenum, newsrv->id);
4970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
4972 }
4973
4974 if (!newsrv->agent.inter)
4975 newsrv->agent.inter = newsrv->check.inter;
4976
4977 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
4978 if (ret) {
4979 err_code |= ret;
4980 goto out;
4981 }
4982
4983 newsrv->state |= SRV_AGENT_CHECKED;
4984 }
4985
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004986 if (!defsrv) {
4987 if (newsrv->state & SRV_BACKUP)
4988 curproxy->srv_bck++;
4989 else
4990 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004991
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004992 newsrv->prev_state = newsrv->state;
4993 }
William Lallemanda73203e2012-03-12 12:48:57 +01004994 }
4995
4996 else if (strcmp(args[0], "unique-id-format") == 0) {
4997 if (!*(args[1])) {
4998 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
5001 }
William Lallemand3203ff42012-11-11 17:30:56 +01005002 if (*(args[2])) {
5003 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
5006 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005007 free(curproxy->conf.uniqueid_format_string);
5008 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005009
Willy Tarreau62a61232013-04-12 18:13:46 +02005010 free(curproxy->conf.uif_file);
5011 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5012 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005013 }
William Lallemanda73203e2012-03-12 12:48:57 +01005014
5015 else if (strcmp(args[0], "unique-id-header") == 0) {
5016 if (!*(args[1])) {
5017 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
5020 }
5021 free(curproxy->header_unique_id);
5022 curproxy->header_unique_id = strdup(args[1]);
5023 }
5024
William Lallemand723b73a2012-02-08 16:37:49 +01005025 else if (strcmp(args[0], "log-format") == 0) {
5026 if (!*(args[1])) {
5027 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
5030 }
William Lallemand3203ff42012-11-11 17:30:56 +01005031 if (*(args[2])) {
5032 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
5035 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005036
Willy Tarreau62a61232013-04-12 18:13:46 +02005037 if (curproxy->conf.logformat_string != default_http_log_format &&
5038 curproxy->conf.logformat_string != default_tcp_log_format &&
5039 curproxy->conf.logformat_string != clf_http_log_format)
5040 free(curproxy->conf.logformat_string);
5041 curproxy->conf.logformat_string = strdup(args[1]);
5042
5043 free(curproxy->conf.lfs_file);
5044 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5045 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005046
5047 /* get a chance to improve log-format error reporting by
5048 * reporting the correct line-number when possible.
5049 */
5050 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5051 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5052 file, linenum, curproxy->id);
5053 err_code |= ERR_WARN;
5054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 }
William Lallemand723b73a2012-02-08 16:37:49 +01005056
William Lallemand0f99e342011-10-12 17:50:54 +02005057 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5058 /* delete previous herited or defined syslog servers */
5059 struct logsrv *back;
5060
5061 if (*(args[1]) != 0) {
5062 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5063 err_code |= ERR_ALERT | ERR_FATAL;
5064 goto out;
5065 }
5066
William Lallemand723b73a2012-02-08 16:37:49 +01005067 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5068 LIST_DEL(&tmplogsrv->list);
5069 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005070 }
5071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005072 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005073 struct logsrv *logsrv;
5074
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005076 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005077 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005078 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005079 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005080 LIST_INIT(&node->list);
5081 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5082 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 }
5084 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005085 struct sockaddr_storage *sk;
5086 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005087
5088 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089
William Lallemand0f99e342011-10-12 17:50:54 +02005090 logsrv->facility = get_log_facility(args[2]);
5091 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
5095
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 }
5097
William Lallemand0f99e342011-10-12 17:50:54 +02005098 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005100 logsrv->level = get_log_level(args[3]);
5101 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
5105
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106 }
5107 }
5108
William Lallemand0f99e342011-10-12 17:50:54 +02005109 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005110 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005111 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005112 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005113 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
5116
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005117 }
5118 }
5119
Willy Tarreau902636f2013-03-10 19:44:48 +01005120 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005121 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005122 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005123 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005124 goto out;
5125 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005126
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005127 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005128
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005129 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005130 if (port1 != port2) {
5131 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5132 file, linenum, args[0], args[1]);
5133 err_code |= ERR_ALERT | ERR_FATAL;
5134 goto out;
5135 }
5136
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005137 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005138 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 }
William Lallemand0f99e342011-10-12 17:50:54 +02005140
5141 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
5143 else {
5144 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5145 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005148 }
5149 }
5150 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005151 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005152 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005153 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005154 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005155
Willy Tarreau977b8e42006-12-29 14:19:17 +01005156 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005157 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005158
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005160 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5161 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005162 err_code |= ERR_ALERT | ERR_FATAL;
5163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005165
5166 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005167 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5168 free(curproxy->conn_src.iface_name);
5169 curproxy->conn_src.iface_name = NULL;
5170 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005171
Willy Tarreau902636f2013-03-10 19:44:48 +01005172 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005173 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005174 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005175 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005176 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005177 goto out;
5178 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005179
5180 proto = protocol_by_family(sk->ss_family);
5181 if (!proto || !proto->connect) {
5182 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005183 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005184 err_code |= ERR_ALERT | ERR_FATAL;
5185 goto out;
5186 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005187
5188 if (port1 != port2) {
5189 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5190 file, linenum, args[0], args[1]);
5191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
5193 }
5194
Willy Tarreauef9a3602012-12-08 22:29:20 +01005195 curproxy->conn_src.source_addr = *sk;
5196 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005197
5198 cur_arg = 2;
5199 while (*(args[cur_arg])) {
5200 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005201#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5202#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005203 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005204 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5205 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005208 }
5209#endif
5210 if (!*args[cur_arg + 1]) {
5211 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5212 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005215 }
5216
5217 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005218 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5219 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005220 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005221 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5222 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005223 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5224 char *name, *end;
5225
5226 name = args[cur_arg+1] + 7;
5227 while (isspace(*name))
5228 name++;
5229
5230 end = name;
5231 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5232 end++;
5233
Willy Tarreauef9a3602012-12-08 22:29:20 +01005234 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5235 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5236 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5237 curproxy->conn_src.bind_hdr_len = end - name;
5238 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5239 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5240 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005241
5242 /* now look for an occurrence number */
5243 while (isspace(*end))
5244 end++;
5245 if (*end == ',') {
5246 end++;
5247 name = end;
5248 if (*end == '-')
5249 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005250 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005251 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005252 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005253 }
5254
Willy Tarreauef9a3602012-12-08 22:29:20 +01005255 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005256 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5257 " occurrences values smaller than %d.\n",
5258 file, linenum, MAX_HDR_HISTORY);
5259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
5261 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005262 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005263 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005264
Willy Tarreau902636f2013-03-10 19:44:48 +01005265 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005266 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005267 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005268 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005269 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005270 goto out;
5271 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005272
5273 proto = protocol_by_family(sk->ss_family);
5274 if (!proto || !proto->connect) {
5275 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5276 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
5279 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005280
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005281 if (port1 != port2) {
5282 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5283 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005284 err_code |= ERR_ALERT | ERR_FATAL;
5285 goto out;
5286 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005287 curproxy->conn_src.tproxy_addr = *sk;
5288 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005289 }
5290 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005291#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005292 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005293#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005294#else /* no TPROXY support */
5295 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005296 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005299#endif
5300 cur_arg += 2;
5301 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005302 }
5303
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005304 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5305#ifdef SO_BINDTODEVICE
5306 if (!*args[cur_arg + 1]) {
5307 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5308 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005311 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005312 free(curproxy->conn_src.iface_name);
5313 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5314 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005315 global.last_checks |= LSTCHK_NETADM;
5316#else
5317 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5318 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005319 err_code |= ERR_ALERT | ERR_FATAL;
5320 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005321#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005322 cur_arg += 2;
5323 continue;
5324 }
5325 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005326 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005327 err_code |= ERR_ALERT | ERR_FATAL;
5328 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005331 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5332 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5333 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005338 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005339 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5340 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005341 err_code |= ERR_ALERT | ERR_FATAL;
5342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005344
5345 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005346 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005347 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005348 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350 }
5351 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005352 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005353 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005354 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005355 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005357 }
5358 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005359 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005360 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005361 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005362 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 }
5365 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005366 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005367 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005368 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005369 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 }
5372 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005373 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005374 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005375 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005376 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005378 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005379 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005380 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005381 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005382 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005383 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005384 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005385 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005386 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005387 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005388 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005389 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005390 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005391 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005392 }
5393 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005394 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005395 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005396 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005397 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005398 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005399 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005401 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5403 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005406 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005407
5408 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005409 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005410 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005411 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005413 }
5414 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005415 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005416 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005417 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005418 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005420 }
5421 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005422 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005423 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005424 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005425 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 }
5428 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005429 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005430 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005431 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005432 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005434 }
5435 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005436 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005437 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005438 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005439 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005441 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005442 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005443 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005444 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005445 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005446 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005447 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005448 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005449 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005450 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005451
Willy Tarreaubaaee002006-06-26 02:48:02 +02005452 if (curproxy == &defproxy) {
5453 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005456 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005457 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005458 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005459
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460 if (*(args[1]) == 0) {
5461 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005465
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005466 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005467 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5468 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5469 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005470 err_code |= ERR_ALERT | ERR_FATAL;
5471 goto out;
5472 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005473 err_code |= warnif_cond_conflicts(cond,
5474 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5475 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005476 }
5477 else if (*args[2]) {
5478 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5479 file, linenum, args[0], args[2]);
5480 err_code |= ERR_ALERT | ERR_FATAL;
5481 goto out;
5482 }
5483
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005484 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005485 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005486 wl->s = strdup(args[1]);
5487 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005488 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 }
5490 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005491 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005492 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5493 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005494 err_code |= ERR_ALERT | ERR_FATAL;
5495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005497
Willy Tarreauade5ec42010-01-28 19:33:49 +01005498 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005499 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005500 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005501 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005503 }
5504 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005505 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005506 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005507 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005508 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 }
5511 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005512 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005513 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005514 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005515 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 }
5518 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005519 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5521 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005522 err_code |= ERR_ALERT | ERR_FATAL;
5523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005524 }
5525
Willy Tarreauade5ec42010-01-28 19:33:49 +01005526 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005527 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005528 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005529 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005531 }
5532 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005533 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005534 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005535 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005536 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538 }
5539 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005540 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005541 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005542 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005543 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 }
5546 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005547 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005548
Willy Tarreaubaaee002006-06-26 02:48:02 +02005549 if (curproxy == &defproxy) {
5550 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005554 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005555 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 if (*(args[1]) == 0) {
5558 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005561 }
5562
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005563 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005564 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5565 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5566 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
5569 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005570 err_code |= warnif_cond_conflicts(cond,
5571 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5572 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005573 }
5574 else if (*args[2]) {
5575 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5576 file, linenum, args[0], args[2]);
5577 err_code |= ERR_ALERT | ERR_FATAL;
5578 goto out;
5579 }
5580
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005581 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005582 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005583 wl->s = strdup(args[1]);
5584 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585 }
5586 else if (!strcmp(args[0], "errorloc") ||
5587 !strcmp(args[0], "errorloc302") ||
5588 !strcmp(args[0], "errorloc303")) { /* error location */
5589 int errnum, errlen;
5590 char *err;
5591
Willy Tarreau977b8e42006-12-29 14:19:17 +01005592 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005593 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005594
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005596 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 }
5600
5601 errnum = atol(args[1]);
5602 if (!strcmp(args[0], "errorloc303")) {
5603 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5604 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5605 } else {
5606 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5607 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5608 }
5609
Willy Tarreau0f772532006-12-23 20:51:41 +01005610 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5611 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005612 chunk_destroy(&curproxy->errmsg[rc]);
5613 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005614 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005617
5618 if (rc >= HTTP_ERR_SIZE) {
5619 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5620 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 free(err);
5622 }
5623 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005624 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5625 int errnum, errlen, fd;
5626 char *err;
5627 struct stat stat;
5628
5629 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005630 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005631
5632 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005633 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005634 err_code |= ERR_ALERT | ERR_FATAL;
5635 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005636 }
5637
5638 fd = open(args[2], O_RDONLY);
5639 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5640 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5641 file, linenum, args[2], args[1]);
5642 if (fd >= 0)
5643 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005644 err_code |= ERR_ALERT | ERR_FATAL;
5645 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005646 }
5647
Willy Tarreau27a674e2009-08-17 07:23:33 +02005648 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005649 errlen = stat.st_size;
5650 } else {
5651 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005652 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005653 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005654 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005655 }
5656
5657 err = malloc(errlen); /* malloc() must succeed during parsing */
5658 errnum = read(fd, err, errlen);
5659 if (errnum != errlen) {
5660 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5661 file, linenum, args[2], args[1]);
5662 close(fd);
5663 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005664 err_code |= ERR_ALERT | ERR_FATAL;
5665 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005666 }
5667 close(fd);
5668
5669 errnum = atol(args[1]);
5670 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5671 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005672 chunk_destroy(&curproxy->errmsg[rc]);
5673 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005674 break;
5675 }
5676 }
5677
5678 if (rc >= HTTP_ERR_SIZE) {
5679 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5680 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005681 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005682 free(err);
5683 }
5684 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005685 else if (!strcmp(args[0], "compression")) {
5686 struct comp *comp;
5687 if (curproxy->comp == NULL) {
5688 comp = calloc(1, sizeof(struct comp));
5689 curproxy->comp = comp;
5690 } else {
5691 comp = curproxy->comp;
5692 }
5693
5694 if (!strcmp(args[1], "algo")) {
5695 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005696 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005697
William Lallemand82fe75c2012-10-23 10:25:10 +02005698 cur_arg = 2;
5699 if (!*args[cur_arg]) {
5700 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5701 file, linenum, args[0]);
5702 err_code |= ERR_ALERT | ERR_FATAL;
5703 goto out;
5704 }
5705 while (*(args[cur_arg])) {
5706 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5707 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5708 file, linenum, args[0], args[cur_arg]);
5709 err_code |= ERR_ALERT | ERR_FATAL;
5710 goto out;
5711 }
William Lallemand552df672012-11-07 13:21:47 +01005712 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5713 curproxy->comp->algos->end(&ctx);
5714 } else {
5715 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5716 file, linenum, args[0], args[cur_arg]);
5717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
5719 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005720 cur_arg ++;
5721 continue;
5722 }
5723 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005724 else if (!strcmp(args[1], "offload")) {
5725 comp->offload = 1;
5726 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005727 else if (!strcmp(args[1], "type")) {
5728 int cur_arg;
5729 cur_arg = 2;
5730 if (!*args[cur_arg]) {
5731 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5732 file, linenum, args[0]);
5733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
5735 }
5736 while (*(args[cur_arg])) {
5737 comp_append_type(comp, args[cur_arg]);
5738 cur_arg ++;
5739 continue;
5740 }
5741 }
5742 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005743 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005744 file, linenum, args[0]);
5745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
5747 }
5748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005750 struct cfg_kw_list *kwl;
5751 int index;
5752
5753 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5754 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5755 if (kwl->kw[index].section != CFG_LISTEN)
5756 continue;
5757 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5758 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005759 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005760 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005761 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005764 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005765 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005766 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005767 err_code |= ERR_WARN;
5768 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005769 }
Willy Tarreau93893792009-07-23 13:19:11 +02005770 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005771 }
5772 }
5773 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005774
Willy Tarreau6daf3432008-01-22 16:44:08 +01005775 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 }
Willy Tarreau93893792009-07-23 13:19:11 +02005779 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005780 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005781 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782}
5783
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005784int
5785cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5786{
5787
5788 int err_code = 0;
5789 const char *err;
5790
5791 if (!strcmp(args[0], "userlist")) { /* new userlist */
5792 struct userlist *newul;
5793
5794 if (!*args[1]) {
5795 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5796 file, linenum, args[0]);
5797 err_code |= ERR_ALERT | ERR_FATAL;
5798 goto out;
5799 }
5800
5801 err = invalid_char(args[1]);
5802 if (err) {
5803 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5804 file, linenum, *err, args[0], args[1]);
5805 err_code |= ERR_ALERT | ERR_FATAL;
5806 goto out;
5807 }
5808
5809 for (newul = userlist; newul; newul = newul->next)
5810 if (!strcmp(newul->name, args[1])) {
5811 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5812 file, linenum, args[1]);
5813 err_code |= ERR_WARN;
5814 goto out;
5815 }
5816
5817 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5818 if (!newul) {
5819 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5820 err_code |= ERR_ALERT | ERR_ABORT;
5821 goto out;
5822 }
5823
5824 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5825 newul->name = strdup(args[1]);
5826
5827 if (!newul->groupusers | !newul->name) {
5828 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5829 err_code |= ERR_ALERT | ERR_ABORT;
5830 goto out;
5831 }
5832
5833 newul->next = userlist;
5834 userlist = newul;
5835
5836 } else if (!strcmp(args[0], "group")) { /* new group */
5837 int cur_arg, i;
5838 const char *err;
5839
5840 if (!*args[1]) {
5841 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5842 file, linenum, args[0]);
5843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
5845 }
5846
5847 err = invalid_char(args[1]);
5848 if (err) {
5849 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5850 file, linenum, *err, args[0], args[1]);
5851 err_code |= ERR_ALERT | ERR_FATAL;
5852 goto out;
5853 }
5854
5855 for(i = 0; i < userlist->grpcnt; i++)
5856 if (!strcmp(userlist->groups[i], args[1])) {
5857 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5858 file, linenum, args[1], userlist->name);
5859 err_code |= ERR_ALERT;
5860 goto out;
5861 }
5862
5863 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5864 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5865 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5866 err_code |= ERR_ALERT | ERR_FATAL;
5867 goto out;
5868 }
5869
5870 cur_arg = 2;
5871
5872 while (*args[cur_arg]) {
5873 if (!strcmp(args[cur_arg], "users")) {
5874 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5875 cur_arg += 2;
5876 continue;
5877 } else {
5878 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5879 file, linenum, args[0]);
5880 err_code |= ERR_ALERT | ERR_FATAL;
5881 goto out;
5882 }
5883 }
5884
5885 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5886 } else if (!strcmp(args[0], "user")) { /* new user */
5887 struct auth_users *newuser;
5888 int cur_arg;
5889
5890 if (!*args[1]) {
5891 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5892 file, linenum, args[0]);
5893 err_code |= ERR_ALERT | ERR_FATAL;
5894 goto out;
5895 }
5896
5897 for (newuser = userlist->users; newuser; newuser = newuser->next)
5898 if (!strcmp(newuser->user, args[1])) {
5899 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5900 file, linenum, args[1], userlist->name);
5901 err_code |= ERR_ALERT;
5902 goto out;
5903 }
5904
5905 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5906 if (!newuser) {
5907 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5908 err_code |= ERR_ALERT | ERR_ABORT;
5909 goto out;
5910 }
5911
5912 newuser->user = strdup(args[1]);
5913
5914 newuser->next = userlist->users;
5915 userlist->users = newuser;
5916
5917 cur_arg = 2;
5918
5919 while (*args[cur_arg]) {
5920 if (!strcmp(args[cur_arg], "password")) {
5921#ifndef CONFIG_HAP_CRYPT
5922 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5923 file, linenum);
5924 err_code |= ERR_ALERT;
5925#endif
5926 newuser->pass = strdup(args[cur_arg + 1]);
5927 cur_arg += 2;
5928 continue;
5929 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5930 newuser->pass = strdup(args[cur_arg + 1]);
5931 newuser->flags |= AU_O_INSECURE;
5932 cur_arg += 2;
5933 continue;
5934 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005935 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005936 cur_arg += 2;
5937 continue;
5938 } else {
5939 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5940 file, linenum, args[0]);
5941 err_code |= ERR_ALERT | ERR_FATAL;
5942 goto out;
5943 }
5944 }
5945 } else {
5946 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5947 err_code |= ERR_ALERT | ERR_FATAL;
5948 }
5949
5950out:
5951 return err_code;
5952}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005953
5954/*
5955 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005956 * Returns the error code, 0 if OK, or any combination of :
5957 * - ERR_ABORT: must abort ASAP
5958 * - ERR_FATAL: we can continue parsing but not start the service
5959 * - ERR_WARN: a warning has been emitted
5960 * - ERR_ALERT: an alert has been emitted
5961 * Only the two first ones can stop processing, the two others are just
5962 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005963 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005964int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005965{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005966 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005967 FILE *f;
5968 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005969 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005970 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005971
Willy Tarreaubaaee002006-06-26 02:48:02 +02005972 if ((f=fopen(file,"r")) == NULL)
5973 return -1;
5974
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005975 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005976 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005977 char *end;
5978 char *args[MAX_LINE_ARGS + 1];
5979 char *line = thisline;
5980
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 linenum++;
5982
5983 end = line + strlen(line);
5984
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005985 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5986 /* Check if we reached the limit and the last char is not \n.
5987 * Watch out for the last line without the terminating '\n'!
5988 */
5989 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005990 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005991 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005992 }
5993
Willy Tarreaubaaee002006-06-26 02:48:02 +02005994 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005995 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005996 line++;
5997
5998 arg = 0;
5999 args[arg] = line;
6000
6001 while (*line && arg < MAX_LINE_ARGS) {
6002 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6003 * C equivalent value. Other combinations left unchanged (eg: \1).
6004 */
6005 if (*line == '\\') {
6006 int skip = 0;
6007 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6008 *line = line[1];
6009 skip = 1;
6010 }
6011 else if (line[1] == 'r') {
6012 *line = '\r';
6013 skip = 1;
6014 }
6015 else if (line[1] == 'n') {
6016 *line = '\n';
6017 skip = 1;
6018 }
6019 else if (line[1] == 't') {
6020 *line = '\t';
6021 skip = 1;
6022 }
6023 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006024 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006025 unsigned char hex1, hex2;
6026 hex1 = toupper(line[2]) - '0';
6027 hex2 = toupper(line[3]) - '0';
6028 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6029 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6030 *line = (hex1<<4) + hex2;
6031 skip = 3;
6032 }
6033 else {
6034 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006035 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006036 }
6037 }
6038 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006039 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006040 end -= skip;
6041 }
6042 line++;
6043 }
6044 else if (*line == '#' || *line == '\n' || *line == '\r') {
6045 /* end of string, end of loop */
6046 *line = 0;
6047 break;
6048 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006049 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006050 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006051 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006052 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053 line++;
6054 args[++arg] = line;
6055 }
6056 else {
6057 line++;
6058 }
6059 }
6060
6061 /* empty line */
6062 if (!**args)
6063 continue;
6064
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006065 if (*line) {
6066 /* we had to stop due to too many args.
6067 * Let's terminate the string, print the offending part then cut the
6068 * last arg.
6069 */
6070 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6071 line++;
6072 *line = '\0';
6073
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006074 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006075 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006076 err_code |= ERR_ALERT | ERR_FATAL;
6077 args[arg] = line;
6078 }
6079
Willy Tarreau540abe42007-05-02 20:50:16 +02006080 /* zero out remaining args and ensure that at least one entry
6081 * is zeroed out.
6082 */
6083 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006084 args[arg] = line;
6085 }
6086
Willy Tarreau3842f002009-06-14 11:39:52 +02006087 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006088 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006089 char *tmp;
6090
Willy Tarreau3842f002009-06-14 11:39:52 +02006091 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006092 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006093 for (arg=0; *args[arg+1]; arg++)
6094 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006095 *tmp = '\0'; // fix the next arg to \0
6096 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006097 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006098 else if (!strcmp(args[0], "default")) {
6099 kwm = KWM_DEF;
6100 for (arg=0; *args[arg+1]; arg++)
6101 args[arg] = args[arg+1]; // shift args after inversion
6102 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006103
William Lallemand0f99e342011-10-12 17:50:54 +02006104 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6105 strcmp(args[0], "log") != 0) {
6106 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006107 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006108 }
6109
Willy Tarreau977b8e42006-12-29 14:19:17 +01006110 if (!strcmp(args[0], "listen") ||
6111 !strcmp(args[0], "frontend") ||
6112 !strcmp(args[0], "backend") ||
6113 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006114 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006115 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006116 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006117 cursection = strdup(args[0]);
6118 }
6119 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006120 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006121 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006122 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006123 }
6124 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006125 confsect = CFG_USERLIST;
6126 free(cursection);
6127 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006128 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006129 else if (!strcmp(args[0], "peers")) {
6130 confsect = CFG_PEERS;
6131 free(cursection);
6132 cursection = strdup(args[0]);
6133 }
6134
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135 /* else it's a section keyword */
6136
6137 switch (confsect) {
6138 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006139 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006140 break;
6141 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006142 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006143 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006144 case CFG_USERLIST:
6145 err_code |= cfg_parse_users(file, linenum, args, kwm);
6146 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006147 case CFG_PEERS:
6148 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6149 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006150 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006151 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006152 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006153 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006154
6155 if (err_code & ERR_ABORT)
6156 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006158 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006159 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006161 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006162}
6163
Willy Tarreaubb925012009-07-23 13:36:36 +02006164/*
6165 * Returns the error code, 0 if OK, or any combination of :
6166 * - ERR_ABORT: must abort ASAP
6167 * - ERR_FATAL: we can continue parsing but not start the service
6168 * - ERR_WARN: a warning has been emitted
6169 * - ERR_ALERT: an alert has been emitted
6170 * Only the two first ones can stop processing, the two others are just
6171 * indicators.
6172 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006173int check_config_validity()
6174{
6175 int cfgerr = 0;
6176 struct proxy *curproxy = NULL;
6177 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006178 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006179 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006180 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006181 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006183 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006184 /*
6185 * Now, check for the integrity of all that we have collected.
6186 */
6187
6188 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006189 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190
Willy Tarreau193b8c62012-11-22 00:17:38 +01006191 if (!global.tune.max_http_hdr)
6192 global.tune.max_http_hdr = MAX_HTTP_HDR;
6193
6194 if (!global.tune.cookie_len)
6195 global.tune.cookie_len = CAPTURE_LEN;
6196
6197 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6198
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006199 /* first, we will invert the proxy list order */
6200 curproxy = NULL;
6201 while (proxy) {
6202 struct proxy *next;
6203
6204 next = proxy->next;
6205 proxy->next = curproxy;
6206 curproxy = proxy;
6207 if (!next)
6208 break;
6209 proxy = next;
6210 }
6211
Willy Tarreaubaaee002006-06-26 02:48:02 +02006212 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006213 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006214 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006215 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006216 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006217 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006218 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006219 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006220
Willy Tarreau050536d2012-10-04 08:47:34 +02006221 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006222 /* proxy ID not set, use automatic numbering with first
6223 * spare entry starting with next_pxid.
6224 */
6225 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6226 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6227 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006228 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006229 next_pxid++;
6230
Willy Tarreau55ea7572007-06-17 19:56:27 +02006231
Willy Tarreaubaaee002006-06-26 02:48:02 +02006232 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006233 /* ensure we don't keep listeners uselessly bound */
6234 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006235 curproxy = curproxy->next;
6236 continue;
6237 }
6238
Willy Tarreau16a21472012-11-19 12:39:59 +01006239 /* number of processes this proxy is bound to */
6240 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6241
Willy Tarreauff01a212009-03-15 13:46:16 +01006242 switch (curproxy->mode) {
6243 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006244 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006245 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006246 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6247 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006248 cfgerr++;
6249 }
6250
6251 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006252 Warning("config : servers will be ignored for %s '%s'.\n",
6253 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006254 break;
6255
6256 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006257 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006258 break;
6259
6260 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006261 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006262 break;
6263 }
6264
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006265 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006266 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006267 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006268 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6269 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006270 cfgerr++;
6271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006272#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006273 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006274 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6275 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006276 cfgerr++;
6277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006278#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006279 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006280 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6281 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006282 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006283 }
6284 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006285 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006286 /* If no LB algo is set in a backend, and we're not in
6287 * transparent mode, dispatch mode nor proxy mode, we
6288 * want to use balance roundrobin by default.
6289 */
6290 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6291 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006292 }
6293 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006294
Willy Tarreau1620ec32011-08-06 17:05:02 +02006295 if (curproxy->options & PR_O_DISPATCH)
6296 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6297 else if (curproxy->options & PR_O_HTTP_PROXY)
6298 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6299 else if (curproxy->options & PR_O_TRANSP)
6300 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006301
Willy Tarreau1620ec32011-08-06 17:05:02 +02006302 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6303 if (curproxy->options & PR_O_DISABLE404) {
6304 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6305 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6306 err_code |= ERR_WARN;
6307 curproxy->options &= ~PR_O_DISABLE404;
6308 }
6309 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6310 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6311 "send-state", proxy_type_str(curproxy), curproxy->id);
6312 err_code |= ERR_WARN;
6313 curproxy->options &= ~PR_O2_CHK_SNDST;
6314 }
Willy Tarreauef781042010-01-27 11:53:01 +01006315 }
6316
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006317 /* if a default backend was specified, let's find it */
6318 if (curproxy->defbe.name) {
6319 struct proxy *target;
6320
Alex Williams96532db2009-11-01 21:27:13 -05006321 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006322 if (!target) {
6323 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6324 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006325 cfgerr++;
6326 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006327 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6328 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006329 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006330 } else {
6331 free(curproxy->defbe.name);
6332 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006333 /* we force the backend to be present on at least all of
6334 * the frontend's processes.
6335 */
6336 target->bind_proc = curproxy->bind_proc ?
6337 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006338
6339 /* Emit a warning if this proxy also has some servers */
6340 if (curproxy->srv) {
6341 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6342 curproxy->id);
6343 err_code |= ERR_WARN;
6344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006345 }
6346 }
6347
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006348 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006349 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6350 /* map jump target for ACT_SETBE in req_rep chain */
6351 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006352 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006353 struct proxy *target;
6354
Willy Tarreaua496b602006-12-17 23:15:24 +01006355 if (exp->action != ACT_SETBE)
6356 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006357
Alex Williams96532db2009-11-01 21:27:13 -05006358 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006359 if (!target) {
6360 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6361 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006362 cfgerr++;
6363 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006364 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6365 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006366 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006367 } else {
6368 free((void *)exp->replace);
6369 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006370 /* we force the backend to be present on at least all of
6371 * the frontend's processes.
6372 */
6373 target->bind_proc = curproxy->bind_proc ?
6374 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006375 }
6376 }
6377 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006378
6379 /* find the target proxy for 'use_backend' rules */
6380 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006381 struct proxy *target;
6382
Alex Williams96532db2009-11-01 21:27:13 -05006383 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006384
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006385 if (!target) {
6386 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6387 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006388 cfgerr++;
6389 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006390 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6391 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006392 cfgerr++;
6393 } else {
6394 free((void *)rule->be.name);
6395 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006396 /* we force the backend to be present on at least all of
6397 * the frontend's processes.
6398 */
6399 target->bind_proc = curproxy->bind_proc ?
6400 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006401 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006402 }
6403
6404 /* find the target proxy for 'use_backend' rules */
6405 list_for_each_entry(srule, &curproxy->server_rules, list) {
6406 struct server *target = findserver(curproxy, srule->srv.name);
6407
6408 if (!target) {
6409 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6410 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6411 cfgerr++;
6412 continue;
6413 }
6414 free((void *)srule->srv.name);
6415 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006416 }
6417
Emeric Brunb982a3d2010-01-04 15:45:53 +01006418 /* find the target table for 'stick' rules */
6419 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6420 struct proxy *target;
6421
Emeric Brun1d33b292010-01-04 15:47:17 +01006422 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6423 if (mrule->flags & STK_IS_STORE)
6424 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6425
Emeric Brunb982a3d2010-01-04 15:45:53 +01006426 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006427 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006428 else
6429 target = curproxy;
6430
6431 if (!target) {
6432 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6433 curproxy->id, mrule->table.name);
6434 cfgerr++;
6435 }
6436 else if (target->table.size == 0) {
6437 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6438 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6439 cfgerr++;
6440 }
Willy Tarreau12785782012-04-27 21:37:17 +02006441 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6442 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006443 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6444 cfgerr++;
6445 }
6446 else {
6447 free((void *)mrule->table.name);
6448 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006449 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006450 }
6451 }
6452
6453 /* find the target table for 'store response' rules */
6454 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6455 struct proxy *target;
6456
Emeric Brun1d33b292010-01-04 15:47:17 +01006457 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6458
Emeric Brunb982a3d2010-01-04 15:45:53 +01006459 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006460 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006461 else
6462 target = curproxy;
6463
6464 if (!target) {
6465 Alert("Proxy '%s': unable to find store table '%s'.\n",
6466 curproxy->id, mrule->table.name);
6467 cfgerr++;
6468 }
6469 else if (target->table.size == 0) {
6470 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6471 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6472 cfgerr++;
6473 }
Willy Tarreau12785782012-04-27 21:37:17 +02006474 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6475 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006476 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6477 cfgerr++;
6478 }
6479 else {
6480 free((void *)mrule->table.name);
6481 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006482 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006483 }
6484 }
6485
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006486 /* find the target table for 'tcp-request' layer 4 rules */
6487 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6488 struct proxy *target;
6489
Willy Tarreaub4c84932013-07-23 19:15:30 +02006490 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006491 continue;
6492
6493 if (trule->act_prm.trk_ctr.table.n)
6494 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6495 else
6496 target = curproxy;
6497
6498 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006499 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6500 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006501 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006502 cfgerr++;
6503 }
6504 else if (target->table.size == 0) {
6505 Alert("Proxy '%s': table '%s' used but not configured.\n",
6506 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6507 cfgerr++;
6508 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006509 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6510 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6511 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006512 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006513 cfgerr++;
6514 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006515 else {
6516 free(trule->act_prm.trk_ctr.table.n);
6517 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006518 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006519 * to pass a list of counters to track and allocate them right here using
6520 * stktable_alloc_data_type().
6521 */
6522 }
6523 }
6524
Willy Tarreaud1f96522010-08-03 19:34:32 +02006525 /* find the target table for 'tcp-request' layer 6 rules */
6526 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6527 struct proxy *target;
6528
Willy Tarreaub4c84932013-07-23 19:15:30 +02006529 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006530 continue;
6531
6532 if (trule->act_prm.trk_ctr.table.n)
6533 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6534 else
6535 target = curproxy;
6536
6537 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006538 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6539 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006540 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006541 cfgerr++;
6542 }
6543 else if (target->table.size == 0) {
6544 Alert("Proxy '%s': table '%s' used but not configured.\n",
6545 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6546 cfgerr++;
6547 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006548 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6549 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6550 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006551 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006552 cfgerr++;
6553 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006554 else {
6555 free(trule->act_prm.trk_ctr.table.n);
6556 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006557 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006558 * to pass a list of counters to track and allocate them right here using
6559 * stktable_alloc_data_type().
6560 */
6561 }
6562 }
6563
Emeric Brun32da3c42010-09-23 18:39:19 +02006564 if (curproxy->table.peers.name) {
6565 struct peers *curpeers = peers;
6566
6567 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6568 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6569 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006570 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006571 break;
6572 }
6573 }
6574
6575 if (!curpeers) {
6576 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6577 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006578 free((void *)curproxy->table.peers.name);
6579 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006580 cfgerr++;
6581 }
6582 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006583 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6584 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006585 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006586 cfgerr++;
6587 }
6588 }
6589
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006590 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006591 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006592 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6593 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6594 "proxy", curproxy->id);
6595 cfgerr++;
6596 goto out_uri_auth_compat;
6597 }
6598
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006599 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006600 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006601 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006602 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006603
Willy Tarreau95fa4692010-02-01 13:05:50 +01006604 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6605 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006606
6607 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006608 uri_auth_compat_req[i++] = "realm";
6609 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6610 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006611
Willy Tarreau95fa4692010-02-01 13:05:50 +01006612 uri_auth_compat_req[i++] = "unless";
6613 uri_auth_compat_req[i++] = "{";
6614 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6615 uri_auth_compat_req[i++] = "}";
6616 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006617
Willy Tarreauff011f22011-01-06 17:51:27 +01006618 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6619 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006620 cfgerr++;
6621 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006622 }
6623
Willy Tarreauff011f22011-01-06 17:51:27 +01006624 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006625
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006626 if (curproxy->uri_auth->auth_realm) {
6627 free(curproxy->uri_auth->auth_realm);
6628 curproxy->uri_auth->auth_realm = NULL;
6629 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006630
6631 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006632 }
6633out_uri_auth_compat:
6634
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006635 /* compile the log format */
6636 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006637 if (curproxy->conf.logformat_string != default_http_log_format &&
6638 curproxy->conf.logformat_string != default_tcp_log_format &&
6639 curproxy->conf.logformat_string != clf_http_log_format)
6640 free(curproxy->conf.logformat_string);
6641 curproxy->conf.logformat_string = NULL;
6642 free(curproxy->conf.lfs_file);
6643 curproxy->conf.lfs_file = NULL;
6644 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006645 }
6646
Willy Tarreau62a61232013-04-12 18:13:46 +02006647 if (curproxy->conf.logformat_string) {
6648 curproxy->conf.args.ctx = ARGC_LOG;
6649 curproxy->conf.args.file = curproxy->conf.lfs_file;
6650 curproxy->conf.args.line = curproxy->conf.lfs_line;
6651 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006652 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006653 curproxy->conf.args.file = NULL;
6654 curproxy->conf.args.line = 0;
6655 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006656
Willy Tarreau62a61232013-04-12 18:13:46 +02006657 if (curproxy->conf.uniqueid_format_string) {
6658 curproxy->conf.args.ctx = ARGC_UIF;
6659 curproxy->conf.args.file = curproxy->conf.uif_file;
6660 curproxy->conf.args.line = curproxy->conf.uif_line;
6661 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006662 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006663 curproxy->conf.args.file = NULL;
6664 curproxy->conf.args.line = 0;
6665 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006666
6667 /* only now we can check if some args remain unresolved */
6668 cfgerr += smp_resolve_args(curproxy);
6669 if (!cfgerr)
6670 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006671
Willy Tarreau2738a142006-07-08 17:28:09 +02006672 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006673 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006674 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006675 (!curproxy->timeout.connect ||
6676 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006677 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006678 " | While not properly invalid, you will certainly encounter various problems\n"
6679 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006680 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006681 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006682 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006683 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006684
Willy Tarreau1fa31262007-12-03 00:36:16 +01006685 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6686 * We must still support older configurations, so let's find out whether those
6687 * parameters have been set or must be copied from contimeouts.
6688 */
6689 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006690 if (!curproxy->timeout.tarpit ||
6691 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006692 /* tarpit timeout not set. We search in the following order:
6693 * default.tarpit, curr.connect, default.connect.
6694 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006695 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006696 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006697 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006698 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006699 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006700 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006701 }
6702 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006703 (!curproxy->timeout.queue ||
6704 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006705 /* queue timeout not set. We search in the following order:
6706 * default.queue, curr.connect, default.connect.
6707 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006708 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006709 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006710 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006711 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006712 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006713 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006714 }
6715 }
6716
Willy Tarreau1620ec32011-08-06 17:05:02 +02006717 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006718 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6719 curproxy->check_req = (char *)malloc(curproxy->check_len);
6720 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006721 }
6722
Willy Tarreau193b8c62012-11-22 00:17:38 +01006723 /* ensure that cookie capture length is not too large */
6724 if (curproxy->capture_len >= global.tune.cookie_len) {
6725 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6726 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6727 err_code |= ERR_WARN;
6728 curproxy->capture_len = global.tune.cookie_len - 1;
6729 }
6730
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006731 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006732 if (curproxy->nb_req_cap) {
6733 if (curproxy->mode == PR_MODE_HTTP) {
6734 curproxy->req_cap_pool = create_pool("ptrcap",
6735 curproxy->nb_req_cap * sizeof(char *),
6736 MEM_F_SHARED);
6737 } else {
6738 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6739 proxy_type_str(curproxy), curproxy->id);
6740 err_code |= ERR_WARN;
6741 curproxy->to_log &= ~LW_REQHDR;
6742 curproxy->nb_req_cap = 0;
6743 }
6744 }
6745
6746 if (curproxy->nb_rsp_cap) {
6747 if (curproxy->mode == PR_MODE_HTTP) {
6748 curproxy->rsp_cap_pool = create_pool("ptrcap",
6749 curproxy->nb_rsp_cap * sizeof(char *),
6750 MEM_F_SHARED);
6751 } else {
6752 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6753 proxy_type_str(curproxy), curproxy->id);
6754 err_code |= ERR_WARN;
6755 curproxy->to_log &= ~LW_REQHDR;
6756 curproxy->nb_rsp_cap = 0;
6757 }
6758 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006759
Willy Tarreaubaaee002006-06-26 02:48:02 +02006760 /* first, we will invert the servers list order */
6761 newsrv = NULL;
6762 while (curproxy->srv) {
6763 struct server *next;
6764
6765 next = curproxy->srv->next;
6766 curproxy->srv->next = newsrv;
6767 newsrv = curproxy->srv;
6768 if (!next)
6769 break;
6770 curproxy->srv = next;
6771 }
6772
Willy Tarreaudd701652010-05-25 23:03:02 +02006773 /* assign automatic UIDs to servers which don't have one yet */
6774 next_id = 1;
6775 newsrv = curproxy->srv;
6776 while (newsrv != NULL) {
6777 if (!newsrv->puid) {
6778 /* server ID not set, use automatic numbering with first
6779 * spare entry starting with next_svid.
6780 */
6781 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6782 newsrv->conf.id.key = newsrv->puid = next_id;
6783 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6784 }
6785 next_id++;
6786 newsrv = newsrv->next;
6787 }
6788
Willy Tarreau20697042007-11-15 23:26:18 +01006789 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006790 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006791
Willy Tarreau62c3be22012-01-20 13:12:32 +01006792 /*
6793 * If this server supports a maxconn parameter, it needs a dedicated
6794 * tasks to fill the emptied slots when a connection leaves.
6795 * Also, resolve deferred tracking dependency if needed.
6796 */
6797 newsrv = curproxy->srv;
6798 while (newsrv != NULL) {
6799 if (newsrv->minconn > newsrv->maxconn) {
6800 /* Only 'minconn' was specified, or it was higher than or equal
6801 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6802 * this will avoid further useless expensive computations.
6803 */
6804 newsrv->maxconn = newsrv->minconn;
6805 } else if (newsrv->maxconn && !newsrv->minconn) {
6806 /* minconn was not specified, so we set it to maxconn */
6807 newsrv->minconn = newsrv->maxconn;
6808 }
6809
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006810#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006811 if (newsrv->use_ssl || newsrv->check.use_ssl)
6812 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006813#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006814
Willy Tarreau62c3be22012-01-20 13:12:32 +01006815 if (newsrv->trackit) {
6816 struct proxy *px;
6817 struct server *srv;
6818 char *pname, *sname;
6819
6820 pname = newsrv->trackit;
6821 sname = strrchr(pname, '/');
6822
6823 if (sname)
6824 *sname++ = '\0';
6825 else {
6826 sname = pname;
6827 pname = NULL;
6828 }
6829
6830 if (pname) {
6831 px = findproxy(pname, PR_CAP_BE);
6832 if (!px) {
6833 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6834 proxy_type_str(curproxy), curproxy->id,
6835 newsrv->id, pname);
6836 cfgerr++;
6837 goto next_srv;
6838 }
6839 } else
6840 px = curproxy;
6841
6842 srv = findserver(px, sname);
6843 if (!srv) {
6844 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6845 proxy_type_str(curproxy), curproxy->id,
6846 newsrv->id, sname);
6847 cfgerr++;
6848 goto next_srv;
6849 }
6850
6851 if (!(srv->state & SRV_CHECKED)) {
6852 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6853 "tracking as it does not have checks enabled.\n",
6854 proxy_type_str(curproxy), curproxy->id,
6855 newsrv->id, px->id, srv->id);
6856 cfgerr++;
6857 goto next_srv;
6858 }
6859
6860 if (curproxy != px &&
6861 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6862 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6863 "tracking: disable-on-404 option inconsistency.\n",
6864 proxy_type_str(curproxy), curproxy->id,
6865 newsrv->id, px->id, srv->id);
6866 cfgerr++;
6867 goto next_srv;
6868 }
6869
6870 /* if the other server is forced disabled, we have to do the same here */
6871 if (srv->state & SRV_MAINTAIN) {
6872 newsrv->state |= SRV_MAINTAIN;
6873 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006874 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006875 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006876 }
6877
6878 newsrv->track = srv;
6879 newsrv->tracknext = srv->tracknext;
6880 srv->tracknext = newsrv;
6881
6882 free(newsrv->trackit);
6883 newsrv->trackit = NULL;
6884 }
6885 next_srv:
6886 newsrv = newsrv->next;
6887 }
6888
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006889 /* We have to initialize the server lookup mechanism depending
6890 * on what LB algorithm was choosen.
6891 */
6892
6893 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6894 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6895 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006896 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6897 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6898 init_server_map(curproxy);
6899 } else {
6900 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6901 fwrr_init_server_groups(curproxy);
6902 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006903 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006904
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006905 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006906 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6907 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6908 fwlc_init_server_tree(curproxy);
6909 } else {
6910 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6911 fas_init_server_tree(curproxy);
6912 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006913 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006914
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006915 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006916 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6917 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6918 chash_init_server_tree(curproxy);
6919 } else {
6920 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6921 init_server_map(curproxy);
6922 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006923 break;
6924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006925
6926 if (curproxy->options & PR_O_LOGASAP)
6927 curproxy->to_log &= ~LW_BYTES;
6928
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006929 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006930 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006931 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6932 proxy_type_str(curproxy), curproxy->id);
6933 err_code |= ERR_WARN;
6934 }
6935
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006936 if (curproxy->mode != PR_MODE_HTTP) {
6937 int optnum;
6938
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006939 if (curproxy->uri_auth) {
6940 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6941 proxy_type_str(curproxy), curproxy->id);
6942 err_code |= ERR_WARN;
6943 curproxy->uri_auth = NULL;
6944 }
6945
Willy Tarreau87cf5142011-08-19 22:57:24 +02006946 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006947 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6948 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6949 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006950 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006951 }
6952
6953 if (curproxy->options & PR_O_ORGTO) {
6954 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6955 "originalto", proxy_type_str(curproxy), curproxy->id);
6956 err_code |= ERR_WARN;
6957 curproxy->options &= ~PR_O_ORGTO;
6958 }
6959
6960 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6961 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6962 (curproxy->cap & cfg_opts[optnum].cap) &&
6963 (curproxy->options & cfg_opts[optnum].val)) {
6964 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6965 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6966 err_code |= ERR_WARN;
6967 curproxy->options &= ~cfg_opts[optnum].val;
6968 }
6969 }
6970
6971 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6972 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6973 (curproxy->cap & cfg_opts2[optnum].cap) &&
6974 (curproxy->options2 & cfg_opts2[optnum].val)) {
6975 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6976 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6977 err_code |= ERR_WARN;
6978 curproxy->options2 &= ~cfg_opts2[optnum].val;
6979 }
6980 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006981
Pieter Baauwd551fb52013-05-08 22:49:23 +02006982#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006983 if (curproxy->conn_src.bind_hdr_occ) {
6984 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006985 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006986 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006987 err_code |= ERR_WARN;
6988 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006989#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006990 }
6991
Willy Tarreaubaaee002006-06-26 02:48:02 +02006992 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006993 * ensure that we're not cross-dressing a TCP server into HTTP.
6994 */
6995 newsrv = curproxy->srv;
6996 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006997 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006998 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6999 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007000 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007001 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007002
Willy Tarreau0cec3312011-10-31 13:49:26 +01007003 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7004 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7005 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7006 err_code |= ERR_WARN;
7007 }
7008
Willy Tarreau82ffa392013-08-13 17:19:08 +02007009 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7010 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7011 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7012 err_code |= ERR_WARN;
7013 }
7014
Pieter Baauwd551fb52013-05-08 22:49:23 +02007015#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007016 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7017 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007018 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 +01007019 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007020 err_code |= ERR_WARN;
7021 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007022#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007023 newsrv = newsrv->next;
7024 }
7025
Willy Tarreauc1a21672009-08-16 22:37:44 +02007026 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007027 if (!curproxy->accept)
7028 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007029
Willy Tarreauc1a21672009-08-16 22:37:44 +02007030 if (curproxy->tcp_req.inspect_delay ||
7031 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007032 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007033
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007034 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007035 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007036 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007037 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007038
7039 /* both TCP and HTTP must check switching rules */
7040 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7041 }
7042
7043 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007044 if (curproxy->tcp_req.inspect_delay ||
7045 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7046 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7047
Emeric Brun97679e72010-09-23 17:56:44 +02007048 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7049 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7050
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007051 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007052 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007053 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007054 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007055
7056 /* If the backend does requires RDP cookie persistence, we have to
7057 * enable the corresponding analyser.
7058 */
7059 if (curproxy->options2 & PR_O2_RDPC_PRST)
7060 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7061 }
7062
Emeric Brunc52962f2012-11-15 18:28:02 +01007063#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007064 /* Configure SSL for each bind line.
7065 * Note: if configuration fails at some point, the ->ctx member
7066 * remains NULL so that listeners can later detach.
7067 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007068 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007069 if (!bind_conf->is_ssl) {
7070 if (bind_conf->default_ctx) {
7071 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7072 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7073 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007074 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007075 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007076 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007077 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007078 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007079 cfgerr++;
7080 continue;
7081 }
7082
Emeric Brun4b3091e2012-09-24 15:48:52 +02007083 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007084 Alert("Unable to allocate SSL session cache.\n");
7085 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007086 continue;
7087 }
7088
Emeric Brunfc0421f2012-09-07 17:30:07 +02007089 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007090 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007091 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007092#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007093
Willy Tarreaue6b98942007-10-29 01:09:36 +01007094 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007095 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007096 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007097 if (!listener->luid) {
7098 /* listener ID not set, use automatic numbering with first
7099 * spare entry starting with next_luid.
7100 */
7101 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7102 listener->conf.id.key = listener->luid = next_id;
7103 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007104 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007105 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007106
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007107 /* enable separate counters */
7108 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7109 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007110 if (!listener->name)
7111 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007112 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007113
Willy Tarreaue6b98942007-10-29 01:09:36 +01007114 if (curproxy->options & PR_O_TCP_NOLING)
7115 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007116 if (!listener->maxconn)
7117 listener->maxconn = curproxy->maxconn;
7118 if (!listener->backlog)
7119 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007120 if (!listener->maxaccept)
7121 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7122
7123 /* we want to have an optimal behaviour on single process mode to
7124 * maximize the work at once, but in multi-process we want to keep
7125 * some fairness between processes, so we target half of the max
7126 * number of events to be balanced over all the processes the proxy
7127 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7128 * used to disable the limit.
7129 */
7130 if (listener->maxaccept > 0) {
7131 if (nbproc > 1)
7132 listener->maxaccept = (listener->maxaccept + 1) / 2;
7133 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7134 }
7135
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007136 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007137 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007138 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007139 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007140
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007141 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7142 listener->options |= LI_O_TCP_RULES;
7143
Willy Tarreaude3041d2010-05-31 10:56:17 +02007144 if (curproxy->mon_mask.s_addr)
7145 listener->options |= LI_O_CHK_MONNET;
7146
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007147 /* smart accept mode is automatic in HTTP mode */
7148 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007149 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007150 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7151 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007152 }
7153
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007154 /* Release unused SSL configs */
7155 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7156 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007157 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007158#ifdef USE_OPENSSL
7159 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007160 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007161 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007162 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007163 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007164#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007165 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007166
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007167 /* Check multi-process mode compatibility for the current proxy */
7168 if (global.nbproc > 1) {
7169 int nbproc = 0;
7170 if (curproxy->bind_proc) {
7171 int proc;
7172 for (proc = 0; proc < global.nbproc; proc++) {
7173 if (curproxy->bind_proc & (1 << proc)) {
7174 nbproc++;
7175 }
7176 }
7177 } else {
7178 nbproc = global.nbproc;
7179 }
7180 if (curproxy->table.peers.name) {
7181 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7182 curproxy->id);
7183 cfgerr++;
7184 }
7185 if (nbproc > 1) {
7186 if (curproxy->uri_auth) {
7187 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7188 curproxy->id);
7189 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7190 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7191 curproxy->id);
7192 }
7193 }
7194 if (curproxy->appsession_name) {
7195 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7196 curproxy->id);
7197 }
7198 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7199 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7200 curproxy->id);
7201 }
7202 }
7203 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007204
7205 /* create the task associated with the proxy */
7206 curproxy->task = task_new();
7207 if (curproxy->task) {
7208 curproxy->task->context = curproxy;
7209 curproxy->task->process = manage_proxy;
7210 /* no need to queue, it will be done automatically if some
7211 * listener gets limited.
7212 */
7213 curproxy->task->expire = TICK_ETERNITY;
7214 } else {
7215 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7216 curproxy->id);
7217 cfgerr++;
7218 }
7219
Willy Tarreaubaaee002006-06-26 02:48:02 +02007220 curproxy = curproxy->next;
7221 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007222
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007223 /* Check multi-process mode compatibility */
7224 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007225 if (global.stats_fe && !global.stats_fe->bind_proc) {
7226 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 +01007227 }
7228 }
7229
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007230 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7231 struct auth_users *curuser;
7232 int g;
7233
7234 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7235 unsigned int group_mask = 0;
7236 char *group = NULL;
7237
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007238 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007239 continue;
7240
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007241 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007242
7243 for (g = 0; g < curuserlist->grpcnt; g++)
7244 if (!strcmp(curuserlist->groups[g], group))
7245 break;
7246
7247 if (g == curuserlist->grpcnt) {
7248 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7249 curuserlist->name, group, curuser->user);
7250 err_code |= ERR_ALERT | ERR_FATAL;
7251 goto out;
7252 }
7253
7254 group_mask |= (1 << g);
7255 }
7256
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007257 free(curuser->u.groups);
7258 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007259 }
7260
7261 for (g = 0; g < curuserlist->grpcnt; g++) {
7262 char *user = NULL;
7263
7264 if (!curuserlist->groupusers[g])
7265 continue;
7266
7267 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7268 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7269 if (!strcmp(curuser->user, user))
7270 break;
7271
7272 if (!curuser) {
7273 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7274 curuserlist->name, user, curuserlist->groups[g]);
7275 err_code |= ERR_ALERT | ERR_FATAL;
7276 goto out;
7277 }
7278
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007279 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007280 }
7281
7282 free(curuserlist->groupusers[g]);
7283 }
7284
7285 free(curuserlist->groupusers);
7286
7287#ifdef DEBUG_AUTH
7288 for (g = 0; g < curuserlist->grpcnt; g++) {
7289 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7290
7291 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007292 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007293 fprintf(stderr, " %s", curuser->user);
7294 }
7295
7296 fprintf(stderr, "\n");
7297 }
7298#endif
7299
Willy Tarreaufbb78422011-06-05 15:38:35 +02007300 }
7301
7302 /* automatically compute fullconn if not set. We must not do it in the
7303 * loop above because cross-references are not yet fully resolved.
7304 */
7305 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7306 /* If <fullconn> is not set, let's set it to 10% of the sum of
7307 * the possible incoming frontend's maxconns.
7308 */
7309 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7310 struct proxy *fe;
7311 int total = 0;
7312
7313 /* sum up the number of maxconns of frontends which
7314 * reference this backend at least once or which are
7315 * the same one ('listen').
7316 */
7317 for (fe = proxy; fe; fe = fe->next) {
7318 struct switching_rule *rule;
7319 struct hdr_exp *exp;
7320 int found = 0;
7321
7322 if (!(fe->cap & PR_CAP_FE))
7323 continue;
7324
7325 if (fe == curproxy) /* we're on a "listen" instance */
7326 found = 1;
7327
7328 if (fe->defbe.be == curproxy) /* "default_backend" */
7329 found = 1;
7330
7331 /* check if a "use_backend" rule matches */
7332 if (!found) {
7333 list_for_each_entry(rule, &fe->switching_rules, list) {
7334 if (rule->be.backend == curproxy) {
7335 found = 1;
7336 break;
7337 }
7338 }
7339 }
7340
7341 /* check if a "reqsetbe" rule matches */
7342 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7343 if (exp->action == ACT_SETBE &&
7344 (struct proxy *)exp->replace == curproxy) {
7345 found = 1;
7346 break;
7347 }
7348 }
7349
7350 /* now we've checked all possible ways to reference a backend
7351 * from a frontend.
7352 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007353 if (!found)
7354 continue;
7355 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007356 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007357 /* we have the sum of the maxconns in <total>. We only
7358 * keep 10% of that sum to set the default fullconn, with
7359 * a hard minimum of 1 (to avoid a divide by zero).
7360 */
7361 curproxy->fullconn = (total + 9) / 10;
7362 if (!curproxy->fullconn)
7363 curproxy->fullconn = 1;
7364 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007365 }
7366
Willy Tarreau056f5682010-06-06 15:51:11 +02007367 /* initialize stick-tables on backend capable proxies. This must not
7368 * be done earlier because the data size may be discovered while parsing
7369 * other proxies.
7370 */
7371 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007372 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007373
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007374 /*
7375 * Recount currently required checks.
7376 */
7377
7378 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7379 int optnum;
7380
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007381 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7382 if (curproxy->options & cfg_opts[optnum].val)
7383 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007384
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007385 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7386 if (curproxy->options2 & cfg_opts2[optnum].val)
7387 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007388 }
7389
Willy Tarreau122541c2011-09-07 21:24:49 +02007390 if (peers) {
7391 struct peers *curpeers = peers, **last;
7392 struct peer *p, *pb;
7393
7394 /* Remove all peers sections which don't have a valid listener.
7395 * This can happen when a peers section is never referenced and
7396 * does not contain a local peer.
7397 */
7398 last = &peers;
7399 while (*last) {
7400 curpeers = *last;
7401 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007402 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007403 last = &curpeers->next;
7404 continue;
7405 }
7406
7407 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7408 curpeers->id, localpeer);
7409
7410 p = curpeers->remote;
7411 while (p) {
7412 pb = p->next;
7413 free(p->id);
7414 free(p);
7415 p = pb;
7416 }
7417
7418 /* Destroy and unlink this curpeers section.
7419 * Note: curpeers is backed up into *last.
7420 */
7421 free(curpeers->id);
7422 curpeers = curpeers->next;
7423 free(*last);
7424 *last = curpeers;
7425 }
7426 }
7427
Willy Tarreau34eb6712011-10-24 18:15:04 +02007428 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007429 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007430 MEM_F_SHARED);
7431
Willy Tarreaubb925012009-07-23 13:36:36 +02007432 if (cfgerr > 0)
7433 err_code |= ERR_ALERT | ERR_FATAL;
7434 out:
7435 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007436}
7437
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007438/*
7439 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7440 * parsing sessions.
7441 */
7442void cfg_register_keywords(struct cfg_kw_list *kwl)
7443{
7444 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7445}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007446
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007447/*
7448 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7449 */
7450void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7451{
7452 LIST_DEL(&kwl->list);
7453 LIST_INIT(&kwl->list);
7454}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007455
7456/*
7457 * Local variables:
7458 * c-indent-level: 8
7459 * c-basic-offset: 8
7460 * End:
7461 */